問題描述及方案 假設我們在做電商項目,在進行計算時這個丟失精度在產品價格計算就會出現問題,很有可能造成我們手裡有9.99元然後後面會有一堆9,但是呢這些錢無法購買一個10元的商品。 在某些編程語言中有專門處理貨幣的類型,但是Java沒有,不過沒關係我們可以通過 來解決這個問題。 下麵我們來看幾個例子 ...
## 問題描述及方案 - 假設我們在做電商項目,在進行計算時這個丟失精度在產品價格計算就會出現問題,很有可能造成我們手裡有9.99元然後後面會有一堆9,但是呢這些錢無法購買一個10元的商品。 在某些編程語言中有專門處理貨幣的類型,但是Java沒有,不過沒關係我們可以通過`BigDecimal`來解決這個問題。 - 下麵我們來看幾個例子。 **testOne** - ![Test1](http://oo31b5ljj.bkt.clouddn.com/Test1.png) - 這個呢就是Java本身對於浮點計算的時候會丟失精度,一定要註意,一定要註意,它所引起的事情呢基本沒有小事,如果線上上訂購量大的話,會引起大的故障, 可能會導致下不了訂單或是對賬出現問題 **testTwo** - ![Test2](http://oo31b5ljj.bkt.clouddn.com/Test2.png) - 當使用BigDecimal後結果就更亂了,比test1結果還可怕又長又亂,它算出來的數比0.06是多的還是剛纔那個意思,假設我們現在,銀行卡裡面有0.06元然後我買的兩個商品,分別是0.05元和0.01,當我下單的時候如果沒有做處理那麼他需要付的是0.06000000000000000298372437868010820238851010799407958984375這就導致餘額不夠,訂單無法下。這還沒解決,不要緊,接著看 **testThree** - ![Test3](http://oo31b5ljj.bkt.clouddn.com/Test3.png) - 用String的BigDecimal構造器,這個結果就是我們想要的,本身呢BigDecimal這個類型是用它來解決這個問題但是我們在選擇用它的時候,一定一定一定要選擇它的String構造器一旦不用就像test2一樣會發生嚴重過的精度問題,這個原則在《Effective Java》這本書中也有說,是說這個原則如果float和double只能用來做科學計算或者工程計算,但是在商業計算中我們要用BigDecimal。 ## 源碼分析 **1.說明** - 在java.math包中找到API類BigDecimal,然後找到BigDecimal(double)構造方法 ![說明](http://oo31b5ljj.bkt.clouddn.com/說明.png) - 源代碼里寫的很明白這個結果和這個構造器就會產生這個種問題它是無限接近於這麼一個數這個構造器呢不是正好的,而是等於0.1 **2.用法** - ![用法](http://oo31b5ljj.bkt.clouddn.com/用法.png) - 如果用這個構造器呢,把它轉成String,用Double的toString(double),裡面放double然後用BigDecimal(String)這個String去構造,也就是說如果要用的話,就把它轉成String然後在選擇用BigDecimal的String構造器去獲得結果。另外3個這裡就不講了自己去看; - 為了方便我們可以把它寫成一個util類,日後我整理完了會把它放在GitHub上。 原文:http://www.godql.com/blog/2017/05/17/Precision/ 作者:Dr.Lester