산술 연산과 나머지
산술 연산자는 익숙해 보이지만 타입과 평가 순서를 함께 보지 않으면 예상과 다른 결과를 만듭니다.
정수 나눗셈은 소수 부분을 버리고, 나머지는 반복 주기와 범위 제한에 자주 사용됩니다.
피연산자 가운데 하나가 문자열이면 +는 숫자 덧셈이 아니라 연결로 바뀔 수 있습니다.
0으로 나누는 동작도 정수와 부동소수점에서 다릅니다.
이 절에서는 기호를 외우기보다 입력 타입에서 결과 타입과 값을 예측하는 연습을 합니다.
정수와 실수의 나눗셈을 구분한다
7 / 2는 정수 계산이라 3이고 7 / 2.0은 실수 계산이라 3.5입니다.
결과 변수의 타입이 아니라 연산 시점의 피연산자 타입이 기준입니다.
나머지는 주기와 경계를 표현한다
value % size는 순환 인덱스에 유용하지만 음수 피연산자의 결과 부호를 확인해야 합니다.
항상 양의 나머지가 필요하면 Math.floorMod가 의도를 더 잘 표현합니다.
나머지 연산은 단순히 나눗셈의 찌꺼기를 구하는 기능이 아니라 값을 일정한 구간으로 접는 도구입니다. 요일 순환, 원형 버퍼, 홀짝 판별처럼 주기가 있는 문제에서 값 % 주기가 어떤 범위를 만드는지 먼저 적어 봅니다.
public class ArithmeticRules {
public static void main(String[] args) {
System.out.println("7/2=" + 7 / 2);
System.out.println("7/2.0=" + 7 / 2.0);
System.out.println("-1%5=" + -1 % 5);
System.out.println("floorMod=" + Math.floorMod(-1, 5));
System.out.println("sum=" + (2 + 3));
int divisor = 0;
// int zero = 7 / divisor; // 실행 시 ArithmeticException
}
}양수 입력에서는 결과가 0부터 나누는 수 - 1 사이지만 Java에서 음수의 나머지는 음수가 될 수 있습니다. 인덱스로 쓸 값이라면 Math.floorMod(-1, 7)과 -1 % 7을 비교해 정책을 명확히 해야 합니다.
7/2=3
7/2.0=3.5
-1%5=-1
floorMod=4
sum=5양의 순환 인덱스에는 %보다 floorMod가 요구를 직접 표현합니다.
문자열 연결은 왼쪽부터 평가된다
"합계=" + 2 + 3은 합계=23이지만 2 + 3 + "점"은 5점입니다.
숫자 합을 먼저 계산하려면 괄호로 경계를 드러내야 합니다.
"합계=" + 1 + 2는 첫 결합 뒤부터 문자열 연산이 이어져 합계=12가 됩니다. 숫자 합을 원하면 "합계=" + (1 + 2)처럼 계산할 범위를 괄호로 묶어 문자열 결합이 시작되는 시점을 늦춥니다.
System.out.println("합계=" + 2 + 3); // 합계=23
System.out.println("합계=" + (2 + 3)); // 합계=5int max = Integer.MAX_VALUE;
// int checked = Math.addExact(max, 1); // 실행 시 ArithmeticException오버플로가 허용되는지 결정한다
일반 산술은 정수 범위를 넘겨도 예외를 내지 않습니다.
값 손실이 오류라면 Math.addExact, multiplyExact처럼 실패를 드러내는 연산을 선택합니다.
Integer.MAX_VALUE + 1을 출력해 최솟값으로 되감기는지 확인하고, 같은 계산을 Math.addExact로 바꿔 보세요. 조용한 순환이 허용되는 비트 계산인지, 예외로 중단해야 하는 수량 계산인지가 API 선택 기준입니다.
산술식은 연산자 모양보다 각 단계의 타입과 평가 순서를 써 보면 대부분의 혼동을 제거할 수 있습니다.