Java中double值的計(jì)算精準(zhǔn)度問題

很多網(wǎng)上帖子都提到了BigDecimal,但是其實(shí)很多人在使用時(shí)都會用錯(cuò)。

double value1  = 0.9;
double value2 = 0.1;
BigDecimal b1 = new BigDecimal(value1);
BigDecimal b2 = new BigDecimal(value2);
b1.add(b2).doubleValue();

在實(shí)際使用過程中你會發(fā)現(xiàn)這樣使用還是會有精度問題。
大致的原因是:
BigDecimal(double val)將會把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。
對與float也是同樣的道理。首先此函數(shù)會自動進(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));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容