很多網(wǎng)上帖子都提到了BigDecimal,但是其實(shí)很多人在使用時(shí)都會(huì)用錯(cuò)。
double value1 = 0.9;
double value2 = 0.1;
BigDecimal b1 = new BigDecimal(value1);
BigDecimal b2 = new BigDecimal(value2);
b1.add(b2).doubleValue();
在實(shí)際使用過程中你會(huì)發(fā)現(xiàn)這樣使用還是會(huì)有精度問題婉弹。
大致的原因是:
BigDecimal(double val)將會(huì)把double型二進(jìn)制浮點(diǎn)型值精確的轉(zhuǎn)換成十進(jìn)制的BigDecimal荠卷。
你可能認(rèn)為java中用new BigDecimal(0.1)創(chuàng)建的BigDecimal應(yīng)該等于0.1(一個(gè)是1的無精度的值,一個(gè)是有精度的值)瑞你,但實(shí)際上精確的是等于0.1000000000000000055511151231257827021181583404541015625酪惭。這是因?yàn)?.1不能被double精確的表示(下面大概描述一下原理)。因此者甲,傳入構(gòu)造函數(shù)的值不是精確的等于0.1春感。
對(duì)與float也是同樣的道理。首先此函數(shù)會(huì)自動(dòng)進(jìn)行精度擴(kuò)展虏缸,將float類型的0.99轉(zhuǎn)成double類型的鲫懒,因?yàn)?.99本身就是無法用二進(jìn)制表示的,也就說無論你的精度是多少位刽辙,都無法用二進(jìn)制來精確表示0.99窥岩,或者你用二乘來判斷(0.992=1.98 0.982=1.960.96*2=1.92 。宰缤。颂翼。永遠(yuǎn)無法得到一個(gè)整數(shù))。這就是二進(jìn)制計(jì)算機(jī)的缺點(diǎn)慨灭,就如同十進(jìn)制也也無法表示1/3朦乏,1/6一樣。
所以在0.99f轉(zhuǎn)成double時(shí)氧骤,進(jìn)行了精度擴(kuò)展呻疹,變成了0.9900000095367432,而接著轉(zhuǎn)成字符串语淘,最后轉(zhuǎn)成BigDecimal.
解決方法:
所以在當(dāng)遇到需要涉及到精確計(jì)算的時(shí)候诲宇,如上面代碼所示际歼,要注意該構(gòu)造函數(shù)是一個(gè)精確的轉(zhuǎn)換,它無法得到與先調(diào)用Double.toString(double)方法將double轉(zhuǎn)換成String姑蓝,再使用BigDecimal(String)構(gòu)造函數(shù)一樣的結(jié)果鹅心。如果要達(dá)到這種結(jié)果,應(yīng)該使用new BigDecimal(Stringvalue) 或 BigDecimal.valueof( double value)
double value1 = 0.9;
double value2 = 0.1;
BigDecimal b1 = new BigDecimal(String.valueOf(value1));
BigDecimal b2 = new BigDecimal(String.valueOf(value2));