當double需要轉換爲BigDecimal時,精度丟失或者數據異常,結果有誤差,如何解決?
首先,我需要做的是,經過一堆計算得出的值,通過Bigdecimal保留兩位小數,並且第三位小數進行四捨五入。
BigDecimal fee = new BigDecimal(130000 / 100.0 / 12 * 126000 / 1000000 / 10);
Double d = 130000 / 100.0 / 12 * 1 * 126000 / 1000000.0 / 10;
System.out.println(fee.toString());
//輸出結果:1.3649999999999999911182158029987476766109466552734375
System.out.println(d);
//輸出結果:1.365
爲什麼不對?這不是我想要的結果。
業務方反饋,結果有0.01的誤差,因爲當我再給到業務方時,本應是1.365,保留兩位小數,第三位四捨五入,結果應該是1.37纔對。
但最後給到的結果卻是1.36。
問題出在new BigDecimal造成誤差
當double需要轉換爲BigDecimal時,精度丟失或者數據異常,結果有誤差,如何解決?
解決方案總結:
- 將結果轉換成String類型,再使用BigDecimal(String s)構造方法
- 使用BigDecimal.valueOf()方法
System.out.println(new BigDecimal(d.toString()).toString());
//輸出結果:1.365
BigDecimal t = BigDecimal.valueOf(130000 / 100.0 / 12 * 126000 / 1000000 / 10);
//輸出結果:1.365
關於BigDecimal.valueOf(double d),源碼其實也是通過轉換爲String類型來的:
public static BigDecimal valueOf(double val) {
// Reminder: a zero double returns '0.0', so we cannot fastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
return new BigDecimal(Double.toString(val));
}
方案有若干中,這只是我現在着手使用的方法,記錄備案。