Skip to content

[MEJ-014] 기본자료형과 BigDecimal 타입의 활용 방안 #230

@yngbao97

Description

@yngbao97

based on: #226 by @undeadtimo


정확하고 세밀한 계산을 요하는 프로그램에서는 BigDecimal을 사용해야 계산 오류를 방지할 수 있지만, 탐구해주신 내용과 같이 BigDecimal을 사용할 경우 성능에 이슈가 생길 수 있습니다.

기본자료형 float와 double의 비정확성과 BigDecimal의 속도 문제를 보완할 수 있는 다른 방법이 없을까 조금 찾아보았습니다.
BigDecimal을 필요로 하는 상황은 주로 금전계산과 관련이 되어 있는데, 금전 계산을 위한 표준 API인 javax.money를 사용하거나 기본자료형과 BigDecimal을 적절히 함께 사용하는 방법이 가능한 것 같았습니다.

javax.money패키지 또한 내부적으로 기본자료형과 BigDecimal을 사용해 구현하고 있는 것 같아서, 두번째 방법을 간단한 예시 코드로 구현해보았습니다.
온라인 쇼핑몰에서 결제 금액을 계산하는 상황이라고 가정했을때, 정밀도와 처리 속도 모두 중요할 수 있을 것입니다.
따라서 상품 가격이나 수량 등에 대한 계산은 기본자료형을 사용하고, 할인율이나 세금 계산과 같이 정밀한 계산이 필요한 부분은 BigDecimal을 사용해보았습니다.

19,900원짜리 물건 3개를 구매한다고 가정한 예시입니다.

import java.math.BigDecimal;
import java.math.RoundingMode;

public class ShoppingCartCalculator {
    
    // 상품 가격과 구매 개수
    private static final long PRICE = 19900;
    private static final int QUANTITY = 3;

    // 할인율과 세율 각각 10%
    private static final double DISCOUNT_RATE = 0.1;
    private static final double TAX_RATE = 0.1;

    public static void main(String[] args) {
        // 구매 상품 가격
        long totalPrice = PRICE * QUANTITY;
        
        // 할인 금액 계산은 BigDecimal로
        BigDecimal discount = BigDecimal.valueOf(totalPrice)
            .multiply(BigDecimal.valueOf(DISCOUNT_RATE))
            .setScale(0, RoundingMode.HALF_UP); // 반올림 처리
        
        // 할인이 적용
        BigDecimal discountedPrice = BigDecimal.valueOf(totalPrice).subtract(discount);
        
        // 세금 계산
        BigDecimal tax = discountedPrice.multiply(BigDecimal.valueOf(TAX_RATE))
            .setScale(0, RoundingMode.HALF_UP); // 반올림 처리
        
        // 최종 결제 금액 : 할인 적용금액 + 세금
        BigDecimal finalAmount = discountedPrice.add(tax);
        
        // 결과 출력
        System.out.println("총 결제 금액: " + finalAmount + "원");   // 총 결제 금액: 59103원
    }
}

다만, BigDecimal은 불변 객체로, 각 연산에서 새로운 BigDecimal 인스턴스를 반환하기 때문에 그의 메서드를 계속 사용해야 한다는 점에 주의할 필요가 있습니다. 객체 반환을 통해 원본 데이터가 변경되지 않도록 보호해야 하기 때문에 기본 자료형과의 연산이 제한되는 것으로 보입니다.
따라서, 가능한 기본자료형으로 가능한 부분을 먼저 해결한 후 BigDecimal 객체로 넘어가거나 최종 금액을 출력용으로 사용할때만 다시 기본자료형으로 변환하는 것이 좋을 것 같습니다.

Metadata

Metadata

Assignees

Labels

weekly reviewsReview for the docs of others

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions