一、前言
在使用Java,double 進行運算時,經常出現精度丟失的問題,總是在一個正確的結果左右偏0.0000**1。 特別在實際項目中,通過一個公式校驗該值是否大于0,如果大于0我們會做一件事情,小于0我們又處理其他事情。 這樣的情況通過double計算出來的結果去和0比較大小,尤其是有小數點的時候,經常會因為精度丟失而導致程序處理流程出錯。
二、利用BigDecimal進行運算
/** * 對double數據進行取精度. * @param value double數據. * @param scale 精度位數(保留的小數位數). * @param roundingMode 精度取值方式. * @return 精度計算后的數據. */ public static double round(double value, int scale, int roundingMode) { BigDecimal bd = new BigDecimal(value); bd = bd.setScale(scale, roundingMode); double d = bd.doubleValue(); bd = null; return d; } /** * double 相加 * @param d1 * @param d2 * @return */ public double sum(double d1,double d2){ BigDecimal bd1 = new BigDecimal(Double.toString(d1)); BigDecimal bd2 = new BigDecimal(Double.toString(d2)); return bd1.add(bd2).doubleValue(); } /** * double 相減 * @param d1 * @param d2 * @return */ public double sub(double d1,double d2){ BigDecimal bd1 = new BigDecimal(Double.toString(d1)); BigDecimal bd2 = new BigDecimal(Double.toString(d2)); return bd1.subtract(bd2).doubleValue(); } /** * double 乘法 * @param d1 * @param d2 * @return */ public double mul(double d1,double d2){ BigDecimal bd1 = new BigDecimal(Double.toString(d1)); BigDecimal bd2 = new BigDecimal(Double.toString(d2)); return bd1.multiply(bd2).doubleValue(); } /** * double 除法 * @param d1 * @param d2 * @param scale 四舍五入 小數點位數 * @return */ public double div(double d1,double d2,int scale){ // 當然在此之前,你要判斷分母是否為0, // 為0你可以根據實際需求做相應的處理 BigDecimal bd1 = new BigDecimal(Double.toString(d1)); BigDecimal bd2 = new BigDecimal(Double.toString(d2)); return bd1.divide (bd2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
三、BigDecimal的8種舍入模式
在銀行、帳戶、計費等領域,BigDecimal提供了精確的數值計算。其中8種舍入方式值得掌握。
1、ROUND_UP
舍入遠離零的舍入模式。
在丟棄非零部分之前始終增加數字(始終對非零舍棄部分前面的數字加1)。
注意,此舍入模式始終不會減少計算值的大小。
2、ROUND_DOWN
接近零的舍入模式。
在丟棄某部分之前始終不增加數字(從不對舍棄部分前面的數字加1,即截短)。
注意,此舍入模式始終不會增加計算值的大小。
3、ROUND_CEILING
接近正無窮大的舍入模式。
如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;
如果為負,則舍入行為與 ROUND_DOWN 相同。
注意,此舍入模式始終不會減少計算值。
4、ROUND_FLOOR
接近負無窮大的舍入模式。
如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;
如果為負,則舍入行為與 ROUND_UP 相同。
注意,此舍入模式始終不會增加計算值。
5、ROUND_HALF_UP
向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。
如果舍棄部分 >= 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同。
注意,這是我們大多數人在小學時就學過的舍入模式(四舍五入)。
6、ROUND_HALF_DOWN
向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為上舍入的舍入模式。
如果舍棄部分 > 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同(五舍六入)。
7、ROUND_HALF_EVEN
向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。
如果舍棄部分左邊的數字為奇數,則舍入行為與 ROUND_HALF_UP 相同;
如果為偶數,則舍入行為與 ROUND_HALF_DOWN 相同。
注意,在重復進行一系列計算時,此舍入模式可以將累加錯誤減到最小。
此舍入模式也稱為“銀行家舍入法”,主要在美國使用。四舍六入,五分兩種情況。
如果前一位為奇數,則入位,否則舍去。
以下例子為保留小數點1位,那么這種舍入方式下的結果。
1.15>1.2 1.25>1.2
8、ROUND_UNNECESSARY
斷言請求的操作具有精確的結果,因此不需要舍入。
如果對獲得精確結果的操作指定此舍入模式,則拋出ArithmeticException。
?