0Pricing
Java Academy · 강의

금융 계산을 위한 BigDecimal

금액과 세금 계산에서 부동 소수점 정밀도 오류를 피하기 위해 BigDecimal을 사용합니다.

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

재무 계산을 위한 BigDecimal

부동 소수점 형식(double, float)은 이진 표현 때문에 모든 십진수 값을 정확하게 표현할 수 없습니다. 금액과 세금에는 BigDecimal을 사용합니다.

부동 소수점의 문제

이진 부동 소수점은 아주 작은 반올림 오류를 만듭니다. 재무 애플리케이션에서는 이러한 오류가 누적되어 실제 버그를 일으킵니다.

double price = 0.1 + 0.2;
System.out.println(price);          // 0.30000000000000004 (WRONG!)
System.out.println(price == 0.3);   // false

// Real bug: total never equals expected
double total = 0;
for (int i = 0; i < 10; i++) total += 0.1;
System.out.println(total); // 0.9999999999999999

BigDecimal을 안전하게 생성하기

항상 double이 아니라 String에서 BigDecimal을 생성합니다. double 생성자를 사용하면 부동 소수점의 부정확성이 그대로 이어집니다.

import java.math.BigDecimal;

// WRONG: double constructor
BigDecimal wrong = new BigDecimal(0.1);
System.out.println(wrong); // 0.1000000000000000055511...

// CORRECT: String constructor
BigDecimal correct = new BigDecimal("0.1");
System.out.println(correct); // 0.1

// Or use valueOf (also safe)
BigDecimal safe = BigDecimal.valueOf(0.1);
System.out.println(safe); // 0.1

BigDecimal 기본 산술 연산

BigDecimal은 산술 연산에 메서드 호출을 사용합니다. 즉, add(), subtract(), multiply(), divide()를 사용합니다. 이러한 호출은 새로운 BigDecimal 인스턴스를 반환합니다(불변).

import java.math.BigDecimal;

BigDecimal price = new BigDecimal("19.99");
BigDecimal tax   = new BigDecimal("0.08");
BigDecimal qty   = new BigDecimal("3");

BigDecimal subtotal = price.multiply(qty);
BigDecimal taxAmount = subtotal.multiply(tax);
BigDecimal total = subtotal.add(taxAmount);

System.out.println(subtotal);  // 59.97
System.out.println(taxAmount); // 4.7976
System.out.println(total);     // 64.7676

반올림 방식

RoundingMode는 BigDecimal의 반올림 방식을 제어합니다. 주요 방식은 다음과 같습니다:

  • HALF_UP — 일반적인 반올림(0.5는 올림)
  • HALF_EVEN — 은행가 반올림(0.5를 가장 가까운 짝수로 반올림)
  • DOWN — 0을 향해 버림
  • CEILING — 양의 무한대를 향해 반올림
import java.math.*;

BigDecimal val = new BigDecimal("2.565");

System.out.println(val.setScale(2, RoundingMode.HALF_UP));   // 2.57
System.out.println(val.setScale(2, RoundingMode.HALF_EVEN)); // 2.56 (banker's)
System.out.println(val.setScale(2, RoundingMode.DOWN));      // 2.56
System.out.println(val.setScale(2, RoundingMode.CEILING));   // 2.57

나눗셈과 소수 자릿수

BigDecimal로 나눗셈을 수행할 때는 끝나지 않는 소수로 인한 ArithmeticException을 방지하기 위해 소수 자릿수와 반올림 방식을 지정해야 합니다.

import java.math.*;

BigDecimal revenue = new BigDecimal("1000.00");
BigDecimal months  = new BigDecimal("3");

// Without scale → ArithmeticException (non-terminating decimal)
try {
    revenue.divide(months);
} catch (ArithmeticException e) {
    System.out.println("Need to specify scale!");
}

// Correct: specify scale and rounding
BigDecimal monthly = revenue.divide(months, 2, RoundingMode.HALF_UP);
System.out.println(monthly); // 333.33

BigDecimal 비교하기

값을 비교할 때는 equals()가 아니라 compareTo()를 사용합니다. equals()는 소수 자릿수까지 고려합니다. 즉, 2.0과 2.00은 equals()로는 NOT 같지만 compareTo()로는 ARE 같습니다.

import java.math.BigDecimal;

BigDecimal a = new BigDecimal("2.0");
BigDecimal b = new BigDecimal("2.00");

System.out.println(a.equals(b));        // false (different scale)
System.out.println(a.compareTo(b));     // 0 (same value)
System.out.println(a.compareTo(b) == 0); // true

// For sorting in collections
import java.util.*;
List<BigDecimal> prices = Arrays.asList(
    new BigDecimal("3.50"), new BigDecimal("1.00"), new BigDecimal("2.75")
);
Collections.sort(prices);
System.out.println(prices); // [1.00, 2.75, 3.50]

유효 자릿수를 위한 MathContext

MathContext는 정밀도(유효 자릿수)와 반올림 방식을 지정합니다. 소수점 이하 자릿수가 아니라 일관된 유효 자릿수 정밀도가 필요할 때 사용합니다.

import java.math.*;

MathContext mc = new MathContext(4, RoundingMode.HALF_UP);

BigDecimal a = new BigDecimal("1234567");
BigDecimal b = new BigDecimal("3");

BigDecimal result = a.divide(b, mc);
System.out.println(result); // 4.115E+5 (4 significant digits)

// DECIMAL32, DECIMAL64, DECIMAL128 are standard MathContexts
BigDecimal precise = new BigDecimal("355").divide(
    new BigDecimal("113"), MathContext.DECIMAL64);
System.out.println(precise); // 3.141592920353982...

장바구니 예제

항목, 세금, 할인 및 최종 합계를 BigDecimal로 계산하는 완전한 장바구니 예제입니다.

import java.math.*;

record LineItem(String name, BigDecimal price, int qty) {
    BigDecimal subtotal() {
        return price.multiply(new BigDecimal(qty));
    }
}

var items = List.of(
    new LineItem("Laptop",  new BigDecimal("999.00"), 1),
    new LineItem("Case",    new BigDecimal("29.99"),  2),
    new LineItem("Charger", new BigDecimal("49.99"),  1)
);

BigDecimal subtotal = items.stream()
    .map(LineItem::subtotal)
    .reduce(BigDecimal.ZERO, BigDecimal::add);

BigDecimal taxRate = new BigDecimal("0.09");
BigDecimal tax = subtotal.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);
BigDecimal total = subtotal.add(tax);

System.out.println("Subtotal: " + subtotal);
System.out.println("Tax:      " + tax);
System.out.println("Total:    " + total);

Stripe: 센트 단위 통화

Stripe와 같은 결제 처리기는 소수 관련 문제를 완전히 피하기 위해 금액을 정수 센트로 저장합니다. 센트와 화면에 표시할 금액 사이를 변환하는 것은 일반적인 패턴입니다.

import java.math.*;

// Store as cents (long) for database / API
long amountCents = 999_99L; // $999.99

// Convert to BigDecimal for display
BigDecimal amount = BigDecimal
    .valueOf(amountCents)
    .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);

System.out.println("Amount: $" + amount); // Amount: $999.99

// Convert user input back to cents
BigDecimal input = new BigDecimal("49.95");
long cents = input.multiply(new BigDecimal("100"))
    .setScale(0, RoundingMode.HALF_UP).longValueExact();
System.out.println("Cents: " + cents); // Cents: 4995

BigDecimal과 double 중 선택하기

작업에 맞는 형식을 선택합니다:

  • BigDecimal: 정확한 십진수 표현이 중요한 재무 금액, 세금, 청구서
  • double: 속도가 중요하고 작은 오류를 허용할 수 있는 과학 계산, 그래픽, ML
  • int/long 센트: 결제 API 및 데이터베이스의 금액 저장

빠른 확인

소수 자릿수와 관계없이 두 BigDecimal 값이 수치상 같은지 확인하려면 어떤 BigDecimal 비교 메서드를 사용해야 합니까?

복습: 재무 계산을 위한 BigDecimal

핵심 내용:

  • double/단정밀도 부동 소수점형은 반올림 오류를 일으키므로 금액에 절대 사용하지 않습니다
  • double이 아니라 String 또는 BigDecimal.valueOf()에서 BigDecimal을 생성합니다
  • 산술 연산에는 add(), subtract(), multiply(), divide()를 사용합니다
  • 나눗셈을 수행할 때는 항상 소수 자릿수와 RoundingMode를 지정합니다
  • 같음 여부를 확인할 때는 equals()가 아니라 compareTo()를 사용합니다
  • 데이터베이스나 API 작업에서는 금액을 정수 센트로 저장하는 방법을 고려합니다

자주 묻는 질문

“금융 계산을 위한 BigDecimal” 강의는 무료인가요?

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

“금융 계산을 위한 BigDecimal”에서 뭘 배우나요?

금액과 세금 계산에서 부동 소수점 정밀도 오류를 피하기 위해 BigDecimal을 사용합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

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

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

“금융 계산을 위한 BigDecimal” 강의는 얼마나 걸리나요?

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

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

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

이 강의의 모든 강의

  1. Math 클래스 핵심
  2. 정수 연산과 오버플로
  3. 금융 계산을 위한 BigDecimal
  4. NumberFormat과 printf
← Java Academy(으)로 돌아가기