2017-11-20 2 views
0

아래의 경우 BigDecimals가 잘못된 결과를 출력하는 이유를 아는 사람이 있습니까?BigDecimal 잘못된 값

double a = 2400; 
double b = 3600; 
double c = 8; 

MathContext mc = new MathContext(14); 
BigDecimal aa = new BigDecimal(2400); 
BigDecimal bb = new BigDecimal(3600); 
BigDecimal cc = new BigDecimal(8); 

System.out.println("Doubles: " + (a/b*c)); 
System.out.println("Big Ds: " + (aa.divide(bb, mc).multiply(cc))); 

출력 :

Doubles: 5.333333333333333 
Big Ds: 5.33333333333336 

생각과 아이디어를 환영합니다.

+4

Base-2 (double) 대 Base-10 (BigDecimal) 바이너리 표현. 다양한 종류의 반올림 오류. –

+6

10 진수의 1/3 또는 2 진수의 0.1을 정확히 나타낼 수 없습니다. BigDecimal 또는 다른 클래스가 그것을 변경했다고 상상하는 것은 잘못입니다. – duffymo

+0

나누기에 대해 소수 자릿수 14 자리를 지정 했으므로 그 자리에있는 모든 나누기 오류에 8을 곱합니다. – EJP

답변

1

정확히 수동으로 계산됩니다.

2/3: 0.66666666666667 
*8:  5.33333333333336 

2/3: 0.66666666666667 
         8 x 
     ---------------- 
         56 
        48 
       ...  + 
     ---------------- 
*8:  5.33333333333336 

이것은 아마도 많은 사람들의 감각에 반 직관적입니다. 그러나 마지막 7은 0.1/3의 오류가 너무 많습니다. 시간 8 3 오류로 반올림되고, 이렇게 마지막 숫자는 3 + 오류 3 == 6.


분할에 라운딩 에러 최소화하기해진다 :

aa.multiply(cc).divide(bb, mc) 

이중 계산 용도 약 16 자리의 정밀도, 14 비트로 표현됩니다.