0Pricing
Java Academy · 강의

정수 연산과 오버플로

정수 나눗셈, 나머지 연산, 오버플로 동작과 오버플로를 감지하는 방법을 이해합니다.

정수 연산과 오버플로은(는) 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Math 클래스 핵심
  2. 정수 연산과 오버플로
  3. 금융 계산을 위한 BigDecimal
  4. NumberFormat과 printf
← Java Academy(으)로 돌아가기