되자!백엔드개발자

JAVA(자바) - double에 오차 원인/ 주의할점 본문

개발공부/JAVA

JAVA(자바) - double에 오차 원인/ 주의할점

HyunJng 2022. 7. 27. 20:57

double 에 오차가 있는 이유


컴퓨터는 모든 숫자를 2진수로 관리한다.

실수형인 Double 또한 2진수로 저장이 되고 구조는 다음과 같다.

 

double과 float형의 구조

각 부분마다 어떤게 들어가는지는 예시로 확인하면 된다.

ex) 271(10진수) -> 10111001(2진수) -> 1.0111001 * E7 로 바꾸어 저장

     => sign = 0 / exponent = 7(111) / mantissa = 0111001 / 소수점 앞은 무조건 1이기 때문에 저장하지 않는다.

 

double 과 foat모두 mantissa자리에 한계가 있기 때문에 숫자가 클 경우(즉, 소수점 자리가 긴 경우) 데이터유실이 생길 수 있다.또한 때때로 10진수로 된 실수값을 2진수로 변환할 때 무리수로 나오는 문제가 생기게된다. ex) 0.6 

 

 

 

실수를 다룰 때 주의할 점


이런 이유 때문에 실수를 다룰 때는 주의할 점이 있다.

  • 실수 값끼리는 절대 비교 연산자로 비교하지 말아야한다.
    >> 꼭 실수를 정수화 한 후에 비교할 것
     		double d1 = 0.6;
		float f1 = 0.6f;
		
		bResult = (d1 == f1);
		System.out.println("bResult = " + bResult);	// false
        
        // 실수로 변경 or 작은 쪽으로 맞춰주기
		bResult = ((int)d1 * 10 == (int)f1 * 10);
		System.out.println("bResult = " + bResult);	// true
		bResult = ((float)d1 == f1);
		System.out.println("bResult = " + bResult);	// true
  • 프로그램에서 실수로 산술연산은 가급적 하지 않는다.
		int apple = 1;
		float pieceUnit = 0.1f;
		int number = 7;

		// Wrong
		double result = apple - number * pieceUnit;	// 0.30000001192092896
        
     		   // Correct
     	 	  result = (apple * 10 - number ) / 10 // 0.3
  • switch문에서 조건문으로 double과 float형을 넣는 것은 불가능하다.