Java에서 / 또는 % 연산자를 사용할 때, 제수가 정수 0인 경우 RuntimeException 중 하나인 ArithmeticException 발생한다.
1 | int x = 12; |
문제는 / 또는 % 연산자를 사용할 때, 제수가 정수 0이 아닌 실수 0.0 또는 0.0f인 경우이다. 이때는 ArithmeticException이 발생하는 것이 아니라, Infinity(무한), NaN(Not a Number)라는 값이 발생한다.
1 | double a = 3 / 0.0; |
수학적으로 오류가 발생해야 하는 것임에도 ArithmeticException가 발생하지 않는다. 거기다 a, b변수는 double의 자료형임에도 Infinity, NaN 이라는 문자열 형태 데이터가 출력된다.(잘은 모르겠으나, Double wrapper 클래스가 개입하는 것이라고 개인적으로 추측해본다.)
거기다 이 Infinity, NaN는 오라클의 null 값과 비슷 한 특성을 가지고 있다. 오라클의 null에 어떤 연산을 가하면 미지의 쓰레기 값이 발생하는데, 이 java에서의 Infinity, NaN에 어떤 추가적 산술연산을 할경우 Infinity는 계속 Infinity가 되며 NaN도 계속 NaN이 된다.
Double.isInfinite(a)와 Double.isNaN(b)를 이용하여 Infinity와 NaN를 값을 확인 할 수 있다. 따라서 다음과 같이 Infinity, NaN을 방어하는 코드를 만들수 있다.
1 | if(Double.isInfinite(a) || Double.isNaN(a)){ |
하지만 애시당초 0.0 또는 0.0f와 같은 값들을 정수 0로 치환하여 / 또는 % 연산시 자동으로 ArithmeticException가 발생하게 하는 편이 더 편할 것 같다.
마지막으로 Infinity, NaN에 관련하여 생각해야할 문제점이 있다. 그것은 Double.valueOf(x)의 멍청함이다.
1 | double val = Double.valueOf("NaN"); // 오류가 나지 않고 NaN값이 저장된다. |
위 예제를 보면 Double.valueOf의 인자로 문자열 NaN, Infinity를 받는다. 하지만 코드를 실행시 어떠한 오류없이 동작하며 콘솔에는 NaN, Infinity가 출력된다. 재앙이 아닐 수 없다.
정리하자면
java의 산술식에서 0.0또는 0.0f같은 값은 정수 0으로 치환하는 편이 좋아보이며, Double.valueOf함수를 사용시 반드시 Double.isInfinite, Double.isNaN를 통하여 후처리를 해줘야 할 것 같다.