[java] 더블 대 BigDecimal?

부동 소수점 변수를 계산해야하며 동료 가 더 정확하기 때문에 BigDecimal대신 사용할 것을 제안합니다 double. 그러나 나는 그것이 무엇인지, 어떻게 최대한 활용할 수 있는지 알고 싶습니다 BigDecimal.



답변

A BigDecimal는 숫자를 나타내는 정확한 방법입니다. A Double는 특정 정밀도를 가지고 있습니다. 다양한 크기의 두 배 (예 : d1=1000.0d2=0.001) 0.001로 작업하면 크기 차이가 너무 클 때 합산 할 때 모두 삭제 될 수 있습니다 . 이런 BigDecimal일은 일어나지 않을 것입니다.

의 단점 BigDecimal은 느린하다는이며 (인해 프로그램 알고리즘 그렇게 약간 더 어렵다 + - */하지의 과부하).

돈을 다루고 있거나 정밀도가 필수 인 경우을 사용하십시오 BigDecimal. 그렇지 않으면 Doubles충분히 좋은 경향이 있습니다.

그들이 내가 여기보다 더 잘 설명하는 것처럼 javadoc 을 읽는 것이 좋습니다. BigDecimal🙂


답변

영어 실력이 좋지 않으므로 여기서 간단한 예제를 작성하겠습니다.

    double a = 0.02;
    double b = 0.03;
    double c = b - a;
    System.out.println(c);

    BigDecimal _a = new BigDecimal("0.02");
    BigDecimal _b = new BigDecimal("0.03");
    BigDecimal _c = _b.subtract(_a);
    System.out.println(_c);

프로그램 출력 :

0.009999999999999998
0.01

누군가 아직도 더블을 사용하고 싶어? 😉


답변

double과는 크게 두 가지 차이점이 있습니다.

  • 임의 정밀도, BigInteger와 유사하게 임의의 정밀도 및 크기를 포함 할 수 있음
  • Base 2 대신 Base 10에서 BigDecimal은 n * 10 ^ scale입니다. 여기서 n은 임의의 큰 부호있는 정수이며 scale은 소수점을 왼쪽 또는 오른쪽으로 이동하는 자릿수로 생각할 수 있습니다.

화폐 계산에 BigDecimal을 사용해야하는 이유는 숫자를 나타낼 수있는 것이 아니라 십진수 개념으로 표현 될 수 있고 화폐 세계의 거의 모든 숫자를 포함 할 수있는 모든 숫자를 나타낼 수 있기 때문입니다. 누군가에게).


답변

1 / 7십진수 와 같은 분수 값을 쓰면 얻을 수 있습니다.

1/7 = 0.142857142857142857142857142857142857142857...

무한 시퀀스의 142857. 유한 자릿수 만 쓸 수 있으므로 반올림 (또는 잘림) 오류가 발생합니다.

같은 숫자 1/10또는 1/100소수부와 이진수로 표현은 소수점 자리수 후 무한 수있다 :

1/10 = binary 0.0001100110011001100110011001100110...

Doubles 값을 이진수로 저장하므로 산술을 수행하지 않고도 십진수를 이진수로 변환하는 것만으로 오류가 발생할 수 있습니다.

BigDecimal반면에 10 진수 (예 🙂 는 각 10 진수를 그대로 저장합니다. 즉, 10 진수 유형은 일반적인 의미에서 2 진 부동 소수점 또는 고정 소수점 유형보다 정확하지 않지만 (즉 1/7, 정밀도 손실없이 저장할 수 없음 ) 소수 자릿수가 유한 인 숫자의 경우 더 정확합니다. 종종 돈 계산의 경우입니다.

Java BigDecimal는 소수점 양쪽에 임의의 (그러나 유한 한) 자릿수를 가질 수 있으며 사용 가능한 메모리에 의해서만 제한 될 수 있다는 추가 이점이 있습니다.


답변

BigDecimal은 Oracle의 임의 정밀도 숫자 라이브러리입니다. BigDecimal은 Java 언어의 일부이며 재무에서 과학에 이르기까지 다양한 애플리케이션에 유용합니다.

특정 계산에 복식을 사용하는 데 아무런 문제가 없습니다. 그러나 Math.Pi * Math.Pi / 6, 즉 2의 실제 인수 (현재 작업중인 프로젝트)에 대한 Riemann Zeta 함수의 값을 계산하려고한다고 가정합니다. 부동 소수점 나누기는 반올림 오류의 고통스러운 문제를 나타냅니다.

반면 BigDecimal에는 식을 임의의 정밀도로 계산하기위한 많은 옵션이 포함되어 있습니다. BigDecimal Java World에서 아래 +, * 및 /의 Oracle 위치에 설명 된대로 더하기, 곱하기 및 나누기 메소드는 다음과 같습니다.

http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html

compareTo 메소드는 while 및 for 루프에서 특히 유용합니다.

그러나 BigDecimal에 대한 생성자를 사용할 때는주의하십시오. 문자열 생성자는 많은 경우에 매우 유용합니다. 예를 들어 코드

BigDecimal 1/3 = 새로운 BigDecimal ( “0.33333333333”);

무한 반복 숫자를 지정된 정확도로 나타 내기 위해 1/3의 문자열 표현을 사용합니다. 반올림 오류는 대부분 JVM 내부의 어딘가에있을 가능성이 높으므로 반올림 오류는 실제 계산의 대부분을 방해하지 않습니다. 그러나 나는 개인적인 경험을 통해 반올림을 보았습니다. setScale 메소드는 Oracle 문서에서 볼 수 있듯이 이와 관련하여 중요합니다.


답변

계산을 다루는 경우 계산 방법과 사용해야 할 정밀도에 대한 법률이 있습니다. 당신이 실패하면 당신은 불법적 인 일을 할 것입니다. 유일한 실제 이유는 소수의 비트 표현이 정확하지 않기 때문입니다. 바질은 간단히 말해서 가장 좋은 설명이 그 예입니다. 그의 예를 보완하기 위해 다음과 같은 일이 발생합니다.

static void theDoubleProblem1() {
    double d1 = 0.3;
    double d2 = 0.2;
    System.out.println("Double:\t 0,3 - 0,2 = " + (d1 - d2));

    float f1 = 0.3f;
    float f2 = 0.2f;
    System.out.println("Float:\t 0,3 - 0,2 = " + (f1 - f2));

    BigDecimal bd1 = new BigDecimal("0.3");
    BigDecimal bd2 = new BigDecimal("0.2");
    System.out.println("BigDec:\t 0,3 - 0,2 = " + (bd1.subtract(bd2)));
}

산출:

Double:  0,3 - 0,2 = 0.09999999999999998
Float:   0,3 - 0,2 = 0.10000001
BigDec:  0,3 - 0,2 = 0.1

또한 우리는 그것을 가지고 있습니다 :

static void theDoubleProblem2() {
    double d1 = 10;
    double d2 = 3;
    System.out.println("Double:\t 10 / 3 = " + (d1 / d2));

    float f1 = 10f;
    float f2 = 3f;
    System.out.println("Float:\t 10 / 3 = " + (f1 / f2));

    // Exception! 
    BigDecimal bd3 = new BigDecimal("10");
    BigDecimal bd4 = new BigDecimal("3");
    System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4)));
}

우리에게 출력을 제공합니다 :

Double:  10 / 3 = 3.3333333333333335
Float:   10 / 3 = 3.3333333
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion

그러나:

static void theDoubleProblem2() {
    BigDecimal bd3 = new BigDecimal("10");
    BigDecimal bd4 = new BigDecimal("3");
    System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4, 4, BigDecimal.ROUND_HALF_UP)));
}

출력이 있습니다 :

BigDec:  10 / 3 = 3.3333 


답변