Double.NaN으로 값을 비교하지 않는다

등록일: 2014. 08. 11

자바 코딩, 이럴 땐 이렇게: PMD로 배우는 올바른 자바 코딩 방법

  • 배병선 지음
  • 426쪽
  • 28,000원
  • 2014년 05월 28일

Double 객체를 이용해 연산할 때 예외값인 NaN(Not A Number)를 진단하기 위해 Double 객체의 Double.NaN으로 비교하는 경우가 있는데, 안타깝게도 이 경우 개발자의 예측과는 다르게 동작하는 문제가 있다. 예제 1.21.1에서 볼 수 있듯이 errorValue가 Double.NaN 값으로 설정돼 있어도 Doubel.NaN과 같다고 인지하지 못하는 문제가 발생한다.

예제 1.21.1 잘못된 Double.NaN의 사용법

package com.software.basic.problem;

public class BadComparisonExample {
    public static void main(String[] args) {
        // 어떠한 이유로 숫자가 아닌 값(NaN; Not a Number)을 할당
        Double errorValue = Double.NaN;
        // 오류를 검증하기 위해 오류 값을 Double.NaN과 비교
        if(errorValue == Double.NaN) {
            System.out.println("오류 발생");
        } else {
            System.out.println("정상 처리");
        }
    }
}

실행 결과

정상 처리

문제점 진단

PMD에서는 이처럼 잘못된 값 비교를 방지하기 위해 BadComparison 룰을 제공해 Double.NaN으로 값을 비교하는 것을 경고하고 수정하도록 권고한다. 그림 1.21.1은 PMD를 이용해 Double.NaN으로 값을 비교한 코드를 진단한 결과다.

figure-1-21-1
그림 1.21.1 Double.NaN으로 값을 비교한 코드를 BadComparison 룰로 진단한 결과

해결 방안

자바 언어 사양(JLS; Java Language Specification)에 따르면 NaN(Not a Number), 즉 숫자 아님은 정말 숫자가 아니여서 연산자를 이용한 NaN 간의 비교도 불가능하다고 설명한다. 따라서 예제 1.21.1과 같이 두 값이 모두 Double.NaN일 경우 errorValue == Double.NaN으로 비교하는 것은 무의미하다. 이러한 오류를 처리하려면 예제 1.21.2와 같이 isNaN 메서드를 이용해 비교해야 한다.

예제 1.21.2 올바른 Double.NaN 값의 비교 방법

package com.software.basic.solution;

public class BadComparisonExample {
    public static void main(String[] args) {
        // 어떠한 이유로 숫자가 아닌 값(NaN; Not a Number)을 할당
        Double errorValue = Double.NaN;
        // 오류를 검증하기 위해 오류 값을 Double.NaN으로 비교
        if(Double.isNaN(errorValue)) {
            System.out.println("오류 발생");
        } else {
            System.out.println("정상 처리");
        }
    }
}