天天看點

Double轉BigDecimal并保留兩位小數出現異常: java.lang.ArithmeticException: Rounding necessary

分享知識 傳遞快樂

Double 轉 BigDecima l并保留兩位小數出現異常: java.lang.ArithmeticException: Rounding necessary 。

代碼如下:

public static void main(String[] args) {
    Double d1 = 0.10;
    BigDecimal bigDecimal1 = new BigDecimal(d1).setScale(2);
    System.out.println(bigDecimal1);
    
    // 或
    Double d2 = 0.123;
    BigDecimal bigDecimal2 = new BigDecimal(d2).setScale(2);

    System.out.println(bigDecimal2);
}      

輸出結果:

java.lang.ArithmeticException: Rounding necessary

java.lang.ArithmeticException: Rounding necessary      

異常分析:

使用 Double 轉 BigDecimal 并保留兩位小數出現異常: java.lang.ArithmeticException: Rounding necessary 的原因是:精度丢失。

setScale(int newScale) 方法内部調用 setScale(int newScale, int roundingMode) 方法,傳入預設舍入模式:ROUND_UNNECESSARY,在方法内部對精度處理時,如果存在精度丢失則抛出異常,如果不存在精度丢失則不會抛出異常。

解決方案

public static void main(String[] args) {
    Double d = 0.10;
    BigDecimal bigDecimal1 = new BigDecimal(d).setScale(2,BigDecimal.ROUND_FLOOR );
    BigDecimal bigDecimal2 = new BigDecimal(d+"").setScale(2);

    System.out.println(bigDecimal1);
    System.out.println(bigDecimal2);

    // 精度3位以上,結果保留兩位
    d = 0.125;
    BigDecimal bigDecimal2 = new BigDecimal(d + "").setScale(2,BigDecimal.ROUND_FLOOR);

    System.out.println(bigDecimal2);
     
}      

輸出結果

0.10
0.10
0.12      

拓展

public final static int ROUND_DOWN:舍入模式向零舍入。 永遠不要在丢棄的分數之前增加數字(即截斷)。 請注意,此舍入模式永遠不會增加計算值的大小
public final static int ROUND_CEILING:舍入模式向正無窮大舍入。 如果BigDecimal為正數,則表現為ROUND_UP ; 如果為負,則表現為ROUND_DOWN 。 請注意,此舍入模式永遠不會減少計算值。
public final static int ROUND_FLOOR:舍入模式向負無窮大舍入。 如果BigDecimal為正數,則按照ROUND_DOWN進行ROUND_DOWN ; 如果為負,則按照ROUND_UP方式行事。 請注意,此舍入模式不會增加計算值
public final static int ROUND_HALF_DOWN:舍入模式向“最近鄰居”舍入,除非兩個鄰居等距,在這種情況下向下舍入。 如果丢棄的分數 > 0.5,則行為與ROUND_UP ; 否則,行為與ROUND_DOWN 。
public final static int ROUND_HALF_EVEN:舍入模式向“最近鄰居”舍入,除非兩個鄰居等距,在這種情況下,向偶數鄰居舍入。 如果丢棄的分數左邊的數字是奇數,則行為與ROUND_HALF_UP ; 如果為ROUND_HALF_DOWN則表現為ROUND_HALF_DOWN 。 請注意,這是在一系列計算中重複應用時最小化累積誤差的舍入模式。
public final static int ROUND_HALF_UP:舍入模式向“最近鄰居”舍入,除非兩個鄰居等距,在這種情況下向上舍入。 如果丢棄的分數 ≥ 0.5,則行為與ROUND_UP ; 否則,行為與ROUND_DOWN 。 請注意,這是我們大多數人在國小時所教的舍入模式。是常用的四舍五入方式
public final static int ROUND_UNNECESSARY:舍入模式斷言請求的操作具有精确結果,是以不需要舍入。 如果在産生不精确結果的操作上指定了此舍入模式,則會引發ArithmeticException 。
public final static int ROUND_UP:舍入模式從零舍入。 總是在非零丢棄分數之前增加數字。 請注意,此舍入模式永遠不會降低計算值的大小。。