정수 연산과 오버플로
정수 나눗셈, 나머지 연산, 오버플로 동작과 오버플로를 감지하는 방법을 이해합니다.
정수 연산과 오버플로은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
정수 산술과 오버플로
Java의 정수는 크기가 고정되어 있습니다. 계산 결과가 최댓값이나 최솟값을 초과하면 예외 없이 조용히 순환하며, 예외가 발생하지 않습니다. 이를 이해하면 미묘한 버그를 방지할 수 있습니다.
정수 범위
각 정수 형식의 범위는 비트 수에 따라 제한됩니다:
byte: -128부터 127까지short: -32,768부터 32,767까지int: -2,147,483,648부터 2,147,483,647까지long: -9.2 × 10^18부터 9.2 × 10^18까지
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Long.MAX_VALUE); // 9223372036854775807
System.out.println(Byte.MAX_VALUE); // 127오버플로: 조용한 순환
Integer.MAX_VALUE에 1을 더하면 Integer.MIN_VALUE로 순환합니다. 이는 2의 보수 산술이며, Java는 이 경우를 보장하지 않고 예외도 발생시키지 않습니다.
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (overflow!)
byte b = 127;
b++; // wraps to -128
System.out.println(b); // -128
// Real bug: counting votes in a large election with int
int votes = Integer.MAX_VALUE;
votes += 100; // silently wrong
System.out.println(votes); // negative number!Math.addExact로 오버플로 감지
Java 8에서는 Math.addExact(), multiplyExact(), subtractExact()가 도입되었습니다. 이 메서드들은 오버플로가 발생하면 조용히 순환하는 대신 ArithmeticException을 발생시킵니다.
try {
int result = Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException e) {
System.out.println("Overflow detected!"); // prints this
}
try {
long safe = Math.multiplyExact(100_000L, 100_000L);
System.out.println(safe); // 10000000000
} catch (ArithmeticException e) {
System.out.println("Multiply overflow");
}정수 나눗셈과 나머지
정수 나눗셈은 0을 향해 소수 부분을 버립니다. % 연산자는 피제수의 부호를 따르는 나머지를 반환합니다. 0으로 나누면 ArithmeticException이 발생하므로 주의하십시오.
System.out.println(10 / 3); // 3 (not 3.33)
System.out.println(10 % 3); // 1
System.out.println(-10 % 3); // -1 (sign follows dividend)
System.out.println(-10 % -3); // -1
try {
int x = 5 / 0; // ArithmeticException: / by zero
} catch (ArithmeticException e) {
System.out.println(e.getMessage()); // / by zero
}
// Float division by zero gives Infinity, not exception
System.out.println(5.0 / 0); // Infinity큰 숫자를 위한 long 산술
값이 int 범위를 초과할 수 있다면 long을 사용하십시오. 대입하기 전에 오버플로가 발생하는 것을 방지하려면 long 리터럴에 항상 L을 붙이십시오.
// Bug: multiplication done as int, then widened
long wrong = 1_000_000 * 1_000_000; // overflows int!
System.out.println(wrong); // -727379968 (wrong!)
// Fix: one operand is long
long correct = 1_000_000L * 1_000_000L;
System.out.println(correct); // 1000000000000
// Or cast first
long alsOk = (long) 1_000_000 * 1_000_000;
System.out.println(alsOk); // 1000000000000비트 시프트 연산자
비트 시프트 연산자는 2의 거듭제곱을 곱하거나 나누는 빠른 방법입니다:
n << k— 왼쪽 시프트: 2^k를 곱합니다n >> k— 부호 있는 오른쪽 시프트: 2^k로 나눕니다n >>> k— 부호 없는 오른쪽 시프트: 0으로 채웁니다
int n = 8;
System.out.println(n << 1); // 16 (8 * 2)
System.out.println(n << 2); // 32 (8 * 4)
System.out.println(n >> 1); // 4 (8 / 2)
System.out.println(n >> 2); // 2 (8 / 4)
// Check if number is power of 2
boolean isPow2 = n > 0 && (n & (n - 1)) == 0;
System.out.println(isPow2); // true비트 AND, OR, XOR
비트 연산자는 개별 비트에 대해 작동하며 권한, 플래그, 저수준 프로토콜에 사용됩니다.
int a = 0b1010; // 10
int b = 0b1100; // 12
System.out.println(Integer.toBinaryString(a & b)); // 1000 (AND = 8)
System.out.println(Integer.toBinaryString(a | b)); // 1110 (OR = 14)
System.out.println(Integer.toBinaryString(a ^ b)); // 0110 (XOR = 6)
System.out.println(Integer.toBinaryString(~a)); // ...11110101 (NOT)
// Permission flags example
int READ = 0b001;
int WRITE = 0b010;
int EXEC = 0b100;
int perms = READ | WRITE; // user has read+write
System.out.println((perms & EXEC) != 0); // false — no exec숫자 리터럴의 밑줄
Java 7 이상에서는 가독성을 높이기 위해 숫자 리터럴에 밑줄을 사용할 수 있습니다. 컴파일러는 밑줄을 무시합니다.
int million = 1_000_000;
long creditCard = 4_111_1111_1111_1111L;
double pi = 3.141_592_653_589_793;
int hex = 0xFF_EC_D1_2E;
int binary = 0b0001_0101_0110;
System.out.println(million); // 1000000
System.out.println(creditCard); // 4111111111111111임의 정밀도를 위한 BigInteger
값이 long의 범위를 초과하면 BigInteger를 사용하십시오. 오버플로는 발생하지 않지만 기본 형식보다 느립니다. 암호화 키, 팩토리얼, 천문학적으로 큰 수에 사용하면 좋습니다.
import java.math.BigInteger;
BigInteger factorial100 = BigInteger.ONE;
for (int i = 2; i <= 100; i++) {
factorial100 = factorial100.multiply(BigInteger.valueOf(i));
}
System.out.println(factorial100.toString().length() + " digits"); // 158 digits
BigInteger a = new BigInteger("999999999999999999999999999999");
BigInteger b = new BigInteger("1");
System.out.println(a.add(b)); // 1000000000000000000000000000000실습: 오버플로에 안전한 카운터
Math.addExact를 사용하고 오버플로가 발생하면 Long.MAX_VALUE로 대체하여 안전하게 오버플로를 처리하는 카운터 구현 패턴입니다.
class SafeCounter {
private long count = 0;
public void increment() {
try {
count = Math.addExact(count, 1L);
} catch (ArithmeticException e) {
count = Long.MAX_VALUE; // cap at max
}
}
public long get() { return count; }
}
SafeCounter sc = new SafeCounter();
sc.increment();
sc.increment();
System.out.println(sc.get()); // 2빠른 확인
다음 식의 값은 얼마입니까?
long result = 1_000_000 * 1_000_000; System.out.println(result);
복습: 정수 연산과 오버플로
핵심 내용:
- 정수 오버플로는 조용히 순환하며 기본적으로 예외가 발생하지 않습니다
Math.addExact/multiplyExact/subtractExact를 사용하여 오버플로를 감지합니다- 정수 나눗셈은 0을 향해 버림하며, %의 부호는 피제수의 부호를 따릅니다
- 중간 결과가 int의 범위를 넘을 수 있으면 long 리터럴(L 접미사)을 사용합니다
BigInteger는 오버플로 없이 임의로 큰 값을 처리합니다- 비트 시프트 연산자는 2의 거듭제곱을 곱하거나 나눌 때 사용할 수 있는 빠른 대안입니다
자주 묻는 질문
“정수 연산과 오버플로” 강의는 무료인가요?
네 — “정수 연산과 오버플로” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“정수 연산과 오버플로”에서 뭘 배우나요?
정수 나눗셈, 나머지 연산, 오버플로 동작과 오버플로를 감지하는 방법을 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Java Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“정수 연산과 오버플로” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.