2017-11-20 16 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.

関連する問題