Java에서 BigDecimal을 활용한 소수점 계산 문제 해결

  1. 예제 ====
@Test
public void test() {
    System.out.println(0.3 + 0.1);
    System.out.println(0.3 - 0.1);
    System.out.println(0.2 * 0.1);
    System.out.println(0.3 / 0.1);
}

결과

0.4
0.19999999999999998
0.020000000000000004
2.9999999999999996
  1. 설명 ====

float 또는 double 타입은 모두 부동소수점 수이며, 컴퓨터는 이진수 체계를 사용하기 때문에 정확도가 손실될 수 있습니다.

십진수 값은 종종 완벽한 이진 표현을 갖지 못하며, 이로 인해 계산 결과가 실제 값에 가깝지만 정확하지 않을 수 있습니다.

이러한 경우 정밀도 관련 계산에는 BigDecimal 클래스를 사용합니다.

  1. BigDecimal 개요 ==================

Java의 java.math 패키지에서 제공하는 BigDecimal API 클래스는 16자리 이상의 유효 숫자에 대한 정확한 연산을 지원합니다. double 타입 변수는 최대 16자리의 유효 숫자를 처리할 수 있습니다. 실제 애플리케이션에서는 더 큰 수나 작은 수에 대한 연산이 필요할 때 BigDecimal을 사용합니다. float와 double은 과학적 계산이나 공학적 계산에 적합하며, 상업적 계산에서는 BigDecimal을 사용합니다. BigDecimal 객체는 일반적인 산술 연산자를 사용할 수 없으며, 메서드 호출을 통해 연산해야 합니다.

  1. 생성자 소개 ============
BigDecimal(int) // 지정된 정수 값을 가지는 객체 생성
BigDecimal(double) // 지정된 double 값을 가지는 객체 생성 (비권장)
BigDecimal(long) // 지정된 long 값을 가지는 객체 생성
BigDecimal(String) // 지정된 문자열로 표현된 수치 값을 가지는 객체 생성 (권장)

4.1 BigDecimal(double) 예제 (왜 비권장되는가?)

@Test
public void test2() {
    BigDecimal strTest = new BigDecimal("1.11");
    BigDecimal doubleTest = new BigDecimal(1.11);
    System.out.println(strTest);
    System.out.println(doubleTest);
}

결과

1.11
1.1100000000000000976996261670137755572795867919921875

4.2 JDK 설명

  1. double 타입 매개변수를 사용하는 생성자는 예측 불가능한 결과를 초래할 수 있습니다. 예를 들어, new BigDecimal(0.1)로 생성된 BigDecimal 객체는 실제로 0.1과 동일하지 않으며, 이는 0.1이 double로 정확하게 표현되지 않기 때문입니다.

  2. 반면 String 타입 매개변수를 사용하는 생성자는 예측 가능한 결과를 제공합니다. new BigDecimal("0.1")은 정확히 0.1을 나타내는 BigDecimal 객체를 생성합니다. 따라서, 일반적으로 String 생성자를 사용하는 것이 권장됩니다.

  1. BigDecimal(String) 사용 ======================

double 값을 BigDecimal으로 변환해야 하는 경우, Double.toString(double)을 사용하여 문자열로 변환한 후 String 생성자를 사용하거나, BigDecimal.valueOf 메서드를 사용합니다.

@Test
public void test3() {
    BigDecimal test1 = new BigDecimal(Double.toString(1.11));
    BigDecimal test2 = BigDecimal.valueOf(1.11);
    System.out.println(test1);
    System.out.println(test2);
}

결과

1.11
1.11
  1. 반올림 모드 (예: 반올림) ===============

BigDecimal을 반올림하거나 절단하려면 setScale 메서드를 사용할 수 있습니다.

java.math.RoundingMode에서 다양한 반올림 모드를 제공합니다.

@Test
public void test4() {
    BigDecimal test1 = new BigDecimal(Double.toString(1.116));
    BigDecimal test2 = new BigDecimal(Double.toString(-1.116));
    test1 = test1.setScale(2, RoundingMode.HALF_UP);
    test2 = test2.setScale(2, RoundingMode.HALF_UP);
    System.out.println(test1);
    System.out.println(test2);
}

결과

1.12
-1.12

설명

HALF_UP // 가장 가까운 숫자로 반올림; 이 모드를 권장합니다.

태그: java BigDecimal 소수점계산 반올림

6월 1일 17:10에 게시됨