為什么不該用 Double 表示金額及解決方案
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
眾所周知,double 和 float 這些浮點(diǎn)數(shù)其實(shí)是不精確的。 比如 0.1 + 0.2 并不等于 0.3,而是等于 0.30000000000000004——這也一度成為程序員圈子里的經(jīng)典梗。所以用浮點(diǎn)數(shù)表示金額這種需要精確計(jì)算的數(shù)值,是會(huì)出現(xiàn)精度丟失問題的。
再看一個(gè)更實(shí)際的例子,假設(shè)你在做一個(gè)電商系統(tǒng)的金額計(jì)算:
你看,原本應(yīng)該是 1.8 的結(jié)果,卻變成了 1.7999999999999998。如果這是真實(shí)的訂單金額,那可就出大問題了 為什么會(huì)精度丟失為什么會(huì)有這種精度丟失呢?因?yàn)橛?jì)算機(jī)底層都是用二進(jìn)制存儲(chǔ)的,但并不是所有十進(jìn)制數(shù)都能用二進(jìn)制精確表示。各位有興趣的話可以試著算一下 0.1 的二進(jìn)制是多少,算出來可以在評(píng)論區(qū)分享一下。 算了一會(huì)你可能會(huì)發(fā)現(xiàn):這怎么算不完?沒錯(cuò),出現(xiàn)了無限循環(huán)的情況——(0.1)?? = (0.000110011001100...)? 像這種情況,計(jì)算機(jī)就沒辦法用二進(jìn)制精確表示 0.1 了。 而 double 類型在 Java 中占 64 位,按照 IEEE 754 標(biāo)準(zhǔn),其中 1 位是符號(hào)位,11 位是指數(shù)位,52 位是尾數(shù)位。當(dāng)遇到無限循環(huán)的二進(jìn)制小數(shù)時(shí),只能截?cái)啾4?這就導(dǎo)致了精度丟失。 BigDecimal在 Java 中,無論是單精度還是雙精度,表示的都是近似值。 為了表示精確的小數(shù)值,Java 提供了 舉個(gè)例子,數(shù)字 123.45 在 BigDecimal 中:
實(shí)際值就是:12345 × 10?2 = 123.45 用 BigDecimal 來處理剛才的金額計(jì)算:
這下結(jié)果就對(duì)了 equals 的坑在 BigDecimal 中不能用 equals 方法做等值比較,因?yàn)?equals 會(huì)同時(shí)比較無標(biāo)度值和標(biāo)度這兩個(gè)內(nèi)容。
我們都知道 0.1 和 0.10 在數(shù)值上是相等的,但 equals 的結(jié)果卻是 false。這是因?yàn)?
雖然值相同,但它們的標(biāo)度不同,所以 equals 返回 false。 compareTo比較 BigDecimal 大小時(shí)應(yīng)該使用 compareTo 方法,返回值為 1、-1、0,分別代表大于、小于、等于。
創(chuàng)建 BigDecimal 的正確姿勢(shì)創(chuàng)建 BigDecimal 時(shí),建議使用 String 類型的構(gòu)造方法,也就是
如果你用了 還有一個(gè)更方便的方法:
常用的 BigDecimal 運(yùn)算
注意除法操作時(shí),如果不指定精度,遇到除不盡的情況會(huì)拋出 總之,涉及金額計(jì)算時(shí),千萬別圖省事用 double,老老實(shí)實(shí)用 BigDecimal 才是王道。 轉(zhuǎn)自https://www.cnblogs.com/longlonglong777/p/19133663 該文章在 2025/10/11 8:33:59 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |