交易中的金額炸渡,如果以元為單位的話,不可避免的會涉及到小數(shù)丽已,例如62.4元蚌堵。但是因為double無法精確的表示某些小數(shù),如0.4這種的沛婴。所以如果單純使用double作為金額的類型吼畏,不可避免會有精度的損失。為了解決這個問題嘁灯,常常有兩種解決方案泻蚊, 使用BigDecimal和將錢轉為分為單位
BigDecimal
java.math提供的BigDecimal可以表示任意大小且精度完全準確的浮點數(shù),但是在使用中有些場景需要特別注意
1.創(chuàng)建
創(chuàng)建應該使用new BigDecimal(string) 或者BigDecimal.valueOf(double), 避免使用new BigDecimal(double) 丑婿,但是有時這個問題并不一定會暴露出來性雄,例如new BigDecimal(0.5)
2.比較
BigDecimal的比較使用==肯定是錯的,因為對于對象羹奉,==比較的是引用
那么改用equals是否可以呢毅贮?答案也是否定的,因為equals除了比較值之外還會比較精度
正確的做法是使用compareTo尘奏,然后將結果和0比較
3.Denial of Service(DOS)漏洞
當對BigDecimal進行加減乘除時,如果傳入的參數(shù)未經(jīng)嚴格限定病蛉,會產(chǎn)生DoS炫加,例如如下代碼瑰煎, 會導致CPU彪高,持續(xù)了90215ms
String price = "2e111111111";
BigDecimal t = new BigDecimal(price);
t = t.add(new BigDecimal("0.1"));
將單位轉成分
因為金額的最小單位是分俗孝,所以把0.4元轉成40分酒甸,然后使用int或者long來表示
服務端內部都是使用int或者long來交互,顯示時轉成String傳遞給前端赋铝,如"0.4"
結論
BigDecimal使用起來比較復雜插勤,且很容易誤用,推薦使用將單位轉為分的方式