개인룸/도윤

Item60. 정확한 답이 필요하다면 float과 double은 피하라

UroJem 2023. 8. 7. 23:11

float과 double 타입은 실수를 나타내기 위해 사용하는 기본타입으로 컴퓨터에서 실수를 표현하는 방법은 정수에 비해 복잡한데 부동소수점 표준에 의해 실수를 정수와 마찬가지로 2진수로 표현해야 하기 때문이다.

1,2,3과 같은 정수는 2진수로 표현이 가능하지만 0.1 같은 소수는 2진수로 표현할 방법이 없어서 컴퓨터는 그 값과 가장 근사한 값을 반환하게 되고 이 때 부동소수점의 부정확성이 나타난다.

 

부동소수점(浮動小數點, floating point) 방식은 실수를 컴퓨터상에서 근사하여 표현할 때 소수점의 위치를 고정하지 않고 그 위치를 나타내는 수를 따로 적는 것으로, 유효숫자를 나타내는 가수(假數)와 소수점의 위치를 풀이하는 지수(指數)로 나누어 표현한다.

컴퓨터에서는 고정 소수점 방식보다 넓은 범위의 수를 나타낼 수 있어 과학기술 계산에 많이 이용되지만, 근삿값으로 표현되며 고정 소수점 방식보다 연산 속도가 느리기 때문에 별도의 전용 연산 장치를 두는 경우가 많다. 
고정 소수점과 달리 정수 부분과 소수 부분의 자릿수가 일정하지 않으나, 유효 숫자의 자릿수는 정해져 있다.

 

float과 double 타입은 특히 금융관련 계산과는 맞지 않는다.

 

결과값을 출력하기전에 반올림하면 해결되리라 생각할지 모르지만 반올림을 해도 틀린 답이 나올 수 있다.

 

1달러가 있다고 했을때 10센트, 20센트, 30센트 10센트가 더해지는 사탕을 차례로 사먹어본다고 했을 때

4개를 사먹을 수 있고 잔돈은 남지 않을 것이다.

역시 잘못되었다.

 

이 문제를 해결하기 위해 금융계산에서는 BigDecimal, int 혹은 long을 사용해야 한다.

 

BigDecimal을 사용하였고 계산시 부정확한 값이 사용되는걸 막기위해 문자열을 받는 생성자를 사용했다.

올바른 답이 나왔지만 BigDecimal에는 2가지 단점이 있는데 기본 타입보다 쓰기 훨씬 불편하고 느리다.

 

int혹은 long 타입을 쓴다면 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야한다.

달러대신 센트로 계산한 예제이다.

 

핵심정리

정확한 답이 필요한 계산에는 float이나 double을 피하라. 소수점 추적은 시스템에 맡기고, 코딩 시의 불편함이나 성능 저하를 신경쓰지 않겠다면 BigDecimal을 사용해라.

BigDecimal이 제공하는 여덟가지 반올림 모드를 이용하여 반올림을 완벽히 제어할 수 있다.

반면 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하라. 숫자를 아홉자리 십진수로 표현할 수 있다면 int를, 열여덟자리 십진수로 표현할 수 있다면 long을 사용해라

열여덟자리를 넘어가면 BigDecimal을 사용해야 한다.