0Pricing
Java Academy · 강의

금액에 double을 사용하면 안 되는 이유

부동 소수점 정밀도 문제

금액에 double을 사용하면 안 되는 이유은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

위험한 기본 선택

가격을 double에 저장하는 것이 자연스럽게 느껴집니다. 하지만 double은 대부분의 소수 값을 정확하게 표현할 수 없으므로 아주 작은 오류가 발생하고, 이 오류가 금융 계산을 망칠 수 있습니다.

고전적인 놀라움

double로 0.1과 0.2를 더해도 0.3이 되지 않습니다. 아주 작은 반올림 오류가 포함된 값이 됩니다.

public class Main {
    public static void main(String[] args) {
        double result = 0.1 + 0.2;
        System.out.println(result);
    }
}

오류가 발생하는 이유

컴퓨터는 double을 이진수로 저장합니다. 3분의 1을 십진수로 정확하게 쓸 수 없는 것처럼 0.1과 같은 많은 소수는 이진수로 정확하게 쓸 수 없습니다.

가장 가까운 이진 근사값이 저장되므로 오류가 누적됩니다.

오류가 누적됩니다

아주 작은 오류 하나는 문제가 없어 보일 수 있지만, 수천 건의 거래를 반복문으로 처리하면 차이가 누적되어 눈에 띄는 잘못된 결과가 됩니다.

public class Main {
    public static void main(String[] args) {
        double total = 0.0;
        for (int i = 0; i < 10; i++) {
            total += 0.1;
        }
        System.out.println(total);
    }
}

같음 비교 실패

반올림 오류 때문에 계산된 double을 ==로 비교하면 같을 것으로 예상한 경우에도 자주 실패합니다.

public class Main {
    public static void main(String[] args) {
        double a = 0.1 + 0.2;
        double b = 0.3;
        System.out.println(a == b);
    }
}

돈에는 정확성이 필요합니다

금융에서는 1센트보다 작은 단위의 오류도 허용되지 않습니다. 감사 담당자는 합계가 1센트 단위까지 일치하기를 기대합니다.

따라서 돈을 부동소수점 형식으로 저장해서는 안 됩니다.

해결책: BigDecimal

Java는 십진수를 정확하게 저장하는 클래스인 BigDecimal을 제공합니다. 비조정 값과 scale을 따로 추적하므로 0.1은 실제로 0.1을 의미합니다.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.1");
        BigDecimal b = new BigDecimal("0.2");
        System.out.println(a.add(b));
    }
}

항상 문자열 생성자 사용하기

double이 아니라 문자열에서 BigDecimal을 생성하세요. double을 전달하면 이진 오류가 BigDecimal에 그대로 전달됩니다.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal fromDouble = new BigDecimal(0.1);
        BigDecimal fromString = new BigDecimal("0.1");
        System.out.println(fromDouble);
        System.out.println(fromString);
    }
}

또는 valueOf 사용하기

BigDecimal.valueOf는 안전한 간편 방법입니다. double을 표준 문자열 형식으로 변환하므로 원래의 이진 오류를 피할 수 있습니다.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal price = BigDecimal.valueOf(19.99);
        System.out.println(price);
    }
}

센트 단위로 돈 저장하기

간단한 경우에는 long을 사용해 돈을 정수인 센트 단위로 저장하는 방법도 있습니다. 그러면 19.99달러는 1999센트가 되고 모든 계산이 정확한 정수 계산이 됩니다.

public class Main {
    public static void main(String[] args) {
        long cents = 1999;
        long total = cents * 3;
        System.out.println(total + " cents");
    }
}

핵심 정리

작은 오류가 허용되는 과학 및 그래픽 작업에는 float과 double을 사용하세요. 돈이나 반드시 정확해야 하는 값에는 BigDecimal 또는 정수 센트를 사용하세요.

빠른 확인

부동소수점 정밀도에 대해 얼마나 이해했는지 확인해 보세요.

복습

돈을 다룰 때 double이 실패하는 이유를 배웠습니다.

  • 이진 부동소수점은 많은 소수를 정확하게 저장할 수 없습니다
  • 0.1 + 0.2가 0.3과 같지 않은 것과 같은 오류가 누적됩니다
  • 정확한 십진수 연산에는 BigDecimal을 사용하세요
  • 문자열에서 생성하거나 valueOf를 사용하고, 원래의 double에서는 생성하지 마세요
  • 정수 센트로 저장하는 것도 정확한 방법입니다

자주 묻는 질문

“금액에 double을 사용하면 안 되는 이유” 강의는 무료인가요?

네 — “금액에 double을 사용하면 안 되는 이유” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“금액에 double을 사용하면 안 되는 이유”에서 뭘 배우나요?

부동 소수점 정밀도 문제 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“금액에 double을 사용하면 안 되는 이유” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 금액에 double을 사용하면 안 되는 이유
  2. BigDecimal 사용하기
  3. 반올림과 스케일
  4. 큰 수에 BigInteger 사용하기
← Java Academy(으)로 돌아가기