세금 계산 도메인에서 발생하는 부동소수점 정밀도 오류의 원인과 Java BigDecimal을 통한 해결 방법을 다룬다. 이진수 변환 시 발생하는 무한 소수 표현 한계부터 BigDecimal 인스턴스화 주의사항까지 실용적 가이드를 제공한다.
핵심 포인트- 0.1을 10번 더해도 1.0이 되지 않는 이진 부동소수점의 근본적 정밀도 한계
- 세금 계산에서 미세한 오차가 대규모 거래에서 큰 금액 차이로 이어질 수 있어 BigDecimal 사용이 필수
- BigDecimal 인스턴스화 주의: new BigDecimal(0.1)은 double의 부정확함을 그대로 전파, BigDecimal.valueOf(0.1) 또는 new BigDecimal("0.1") 사용 권장
- BigDecimal.valueOf(long) 내부에서 0-10 값을 미리 캐싱해 동일 객체 참조 반환, 메모리 효율 향상
- 나눗셈·곱셈 연산 시 MathContext.DECIMAL64 적용으로 정밀도와 라운딩 정책 명시 필수
상세 정리- 컴퓨터는 10진수를 2진수로 변환할 때 많은 소수가 무한 반복 소수가 되어 정확한 표현 불가
- Java double 타입으로 0.1 + 0.1 + ... (10회)를 수행하면 1.0이 아닌 근사값이 누적됨
- 세율 계산 오차가 대규모 거래에서는 법적·재무적 리스크로 이어질 수 있음
- BigDecimal은 내부적으로 정수와 소수점 위치를 분리 저장해 임의 정밀도 지원
- new BigDecimal(0.1): double 리터럴을 받아 이미 부정확한 double 값을 그대로 사용 - 위험
- BigDecimal.valueOf(0.1): String 변환을 통해 정확한 값 생성 - 권장
- new BigDecimal("0.1"): String 생성자, 신뢰 가능
- 통화 계산 시 가장 작은 단위(원 단위 long 타입)로 저장해 소수 연산 자체를 회피하는 전략도 고려
- 나눗셈 연산은 무한소수 결과가 나올 수 있어 MathContext로 라운딩 모드와 정밀도를 반드시 지정
왜 읽나세금·금융 도메인에서 Java로 정밀 계산을 구현하는 개발자에게 부동소수점 함정과 BigDecimal 올바른 사용법을 간결하게 정리한다.