문제

다음은 매개변수가 홀수인지 확인하는 메서드입니다. 제대로 작동할까요?


public static boolean isOdd(int i){
	return i % 2 == 1;
}


풀이

이 메서드는 홀수인지 판단하는 기능을 하는데 매개변수로 음수가 들어오면 무조건 false 를 리턴합니다. 음수에도 짝수, 홀수의 개념이 있으므로 고려가 되어야 하는데 % 2 연산의 결과가 1 인지 체크하는 것은 양수만 고려한 것입니다. 


a 를 int 자료형, b 를 0 이 아닌 int 자료형의 숫자라고 하면 나머지 연산자는 다음의 공식으로 표현 가능합니다.


(a / b) * b + (a % b) == a

-> a 를 b 로 나눈 몫에 b 를 곱하고, a 를 b 로 나눈 나머지를 더하면 원래 값으로 돌아간다


자바에서는 정수를 나눌 때 버림을 수행하므로 나머지 연산의 결과는 0 이 아닌 값을 반환할 때는 항상 왼쪽 피연산자의 부호와 같게 됩니다.


3 % 2 -> 1

3 % -2 -> 1

-3 % 2 -> -1

-3 % -2 -> -1


isOdd() 메서드는 나머지가 모두 양수라고 가정해서 잘못된 결과를 리턴하는 것입니다. i 가 음의 홀수인 경우 i % 2 는 1 이 아닌 -1 이므로 false 를 리턴하는데, 이 문제를 해결하려면 매개변수가 음수인 경우도 고려를 해야 합니다. 다음의 코드처럼 짝수인 경우 -> 0, 홀수인 경우 -> 0 이 아닌 정수 (양의 홀수는 1, 음의 홀수는 -1) 로 나누어 체크하면 됩니다.


public static boolean isOdd(int i){
	return i % 2 != 0;
}


만약 위의 코드보다 더 좋은 성능을 원한다면, 나머지 연산자보다 비트 AND 연산자 (&) 를 사용하는 것이 좋습니다.


public static boolean isOdd(int i){
	return (i & 1) != 0;
}


정리를 해보면, 나머지 연산자를 사용할 때는 항상 피연산자의 부호와 결과가 어떻게 나올지 생각해 보세요. 피연산자가 음수가 아닌 경우에는 쉽게 예측할 수 있지만 음수인 경우에는 예측하기 어려우니까요.




(조슈아 블로크, 닐 개프터, 『자바 퍼즐러』, 윤인성 옮김, 한빛미디어 (2014.12.04), p25~27 참고)

by kkikkodev 2017. 6. 20. 19:34