1、前言java
一般进行数值计算时,咱们会先将double或float等转为BigDecimal再处理,而后对计算结果经过setScale方法取指定的小数位;可是在这里有时会遇到java.lang.ArithmeticException: Rounding necessary,下面咱们会对此问题进行演示和说明。spa
2、代码示例code
1. 这里以double转BigDecimal后获取不一样小数位值来举例说明,具体以下:ci
public static void main(String[] args) { double d = 10.0000000001; String s = "10.0000000001"; BigDecimal newBigDecimal = new BigDecimal(d); BigDecimal newStringBigDecimal = new BigDecimal(s); BigDecimal valueOfBigDecimal = BigDecimal.valueOf(d); // newBigDecimal=================================== System.out.println("newBigDecimal's scale:" + newBigDecimal.scale()); try { System.out.println("newBigDecimal setScale(50):" + newBigDecimal.setScale(50)); } catch (Exception e) { System.out.println("newBigDecimal setScale(50):" + e); } try { System.out.println("newBigDecimal setScale(49):" + newBigDecimal.setScale(49)); } catch (Exception e) { System.out.println("newBigDecimal setScale(49):" + e); } try { System.out.println("newBigDecimal setScale(48):" + newBigDecimal.setScale(48)); } catch (Exception e) { System.out.println("newBigDecimal setScale(48):" + e); System.out.println("newBigDecimal setScale(48, RoundingMode.HALF_UP):" + newBigDecimal.setScale(48, RoundingMode.HALF_UP)); } // valueOfBigDecimal====================================== System.out.println("valueOfBigDecimal's scale:" + valueOfBigDecimal.scale()); try { System.out.println("valueOfBigDecimal setScale(50):" + valueOfBigDecimal.setScale(50)); } catch (Exception e) { System.out.println("valueOfBigDecimal setScale(50):" + e); } try { System.out.println("valueOfBigDecimal setScale(49):" + valueOfBigDecimal.setScale(49)); } catch (Exception e) { System.out.println("valueOfBigDecimal setScale(49):" + e); } try { System.out.println("valueOfBigDecimal setScale(48):" + valueOfBigDecimal.setScale(48)); } catch (Exception e) { System.out.println("valueOfBigDecimal setScale(48):" + e); System.out.println("valueOfBigDecimal setScale(48, RoundingMode.HALF_UP):" + valueOfBigDecimal.setScale(48, RoundingMode.HALF_UP)); } // newStringBigDecimal====================================== System.out.println("newStringBigDecimal's scale:" + newStringBigDecimal.scale()); try { System.out.println("newStringBigDecimal setScale(50):" + newStringBigDecimal.setScale(50)); } catch (Exception e) { System.out.println("newStringBigDecimal setScale(50):" + e); } try { System.out.println("newStringBigDecimal setScale(49):" + newStringBigDecimal.setScale(49)); } catch (Exception e) { System.out.println("newStringBigDecimal setScale(49):" + e); } try { System.out.println("newStringBigDecimal setScale(48):" + newStringBigDecimal.setScale(48)); } catch (Exception e) { System.out.println("newStringBigDecimal setScale(48):" + e); System.out.println("newStringBigDecimal setScale(48, RoundingMode.HALF_UP):" + newStringBigDecimal.setScale(48, RoundingMode.HALF_UP)); } d = 10.01; s = "10.01"; newBigDecimal = new BigDecimal(d); valueOfBigDecimal = BigDecimal.valueOf(d); newStringBigDecimal = new BigDecimal(s); // newBigDecimal========================================== System.out.println("newBigDecimal's scale:" + newBigDecimal.scale()); try { System.out.println("newBigDecimal setScale(3):" + newBigDecimal.setScale(3)); } catch (Exception e) { System.out.println("newBigDecimal setScale(3):" + e); System.out.println("newBigDecimal setScale(3, RoundingMode.HALF_UP):" + newBigDecimal.setScale(3, RoundingMode.HALF_UP)); } try { System.out.println("newBigDecimal setScale(2):" + newBigDecimal.setScale(2)); } catch (Exception e) { System.out.println("newBigDecimal setScale(2):" + e); System.out.println("newBigDecimal setScale(2, RoundingMode.HALF_UP):" + newBigDecimal.setScale(2, RoundingMode.HALF_UP)); } try { System.out.println("newBigDecimal setScale(1):" + newBigDecimal.setScale(1)); } catch (Exception e) { System.out.println("newBigDecimal setScale(1):" + e); System.out.println("newBigDecimal setScale(1, RoundingMode.HALF_UP):" + newBigDecimal.setScale(1, RoundingMode.HALF_UP)); } // valueOfBigDecimal====================================== System.out.println("valueOfBigDecimal's scale:" + valueOfBigDecimal.scale()); try { System.out.println("valueOfBigDecimal setScale(3):" + valueOfBigDecimal.setScale(3)); } catch (Exception e) { System.out.println("valueOfBigDecimal setScale(3):" + e); } try { System.out.println("valueOfBigDecimal setScale(2):" + valueOfBigDecimal.setScale(2)); } catch (Exception e) { System.out.println("valueOfBigDecimal setScale(2):" + e); } try { System.out.println("valueOfBigDecimal setScale(1):" + valueOfBigDecimal.setScale(1)); } catch (Exception e) { System.out.println("valueOfBigDecimal setScale(1):" + e); System.out.println("valueOfBigDecimal setScale(1, RoundingMode.HALF_UP):" + valueOfBigDecimal.setScale(1, RoundingMode.HALF_UP)); } // // newStringBigDecimal====================================== System.out.println("newStringBigDecimal's scale:" + newStringBigDecimal.scale()); try { System.out.println("newStringBigDecimal setScale(3):" + newStringBigDecimal.setScale(3)); } catch (Exception e) { System.out.println("newStringBigDecimal setScale(3):" + e); } try { System.out.println("newStringBigDecimal setScale(2):" + newStringBigDecimal.setScale(2)); } catch (Exception e) { System.out.println("newStringBigDecimal setScale(2):" + e); } try { System.out.println("newStringBigDecimal setScale(1):" + newStringBigDecimal.setScale(1)); } catch (Exception e) { System.out.println("newStringBigDecimal setScale(1):" + e); System.out.println("newStringBigDecimal setScale(1, RoundingMode.HALF_UP):" + newStringBigDecimal.setScale(1, RoundingMode.HALF_UP)); } }
运算结果以下:文档
newBigDecimal's scale:49 newBigDecimal setScale(50):10.00000000010000000827403709990903735160827636718750 newBigDecimal setScale(49):10.0000000001000000082740370999090373516082763671875 newBigDecimal setScale(48):java.lang.ArithmeticException: Rounding necessary newBigDecimal setScale(48, RoundingMode.HALF_UP):10.000000000100000008274037099909037351608276367188 valueOfBigDecimal's scale:10 valueOfBigDecimal setScale(50):10.00000000010000000000000000000000000000000000000000 valueOfBigDecimal setScale(49):10.0000000001000000000000000000000000000000000000000 valueOfBigDecimal setScale(48):10.000000000100000000000000000000000000000000000000 newStringBigDecimal's scale:10 newStringBigDecimal setScale(50):10.00000000010000000000000000000000000000000000000000 newStringBigDecimal setScale(49):10.0000000001000000000000000000000000000000000000000 newStringBigDecimal setScale(48):10.000000000100000000000000000000000000000000000000 newBigDecimal's scale:49 newBigDecimal's value:10.0099999999999997868371792719699442386627197265625 newBigDecimal setScale(3):java.lang.ArithmeticException: Rounding necessary newBigDecimal setScale(3, RoundingMode.HALF_UP):10.010 newBigDecimal setScale(2):java.lang.ArithmeticException: Rounding necessary newBigDecimal setScale(2, RoundingMode.HALF_UP):10.01 newBigDecimal setScale(1):java.lang.ArithmeticException: Rounding necessary newBigDecimal setScale(1, RoundingMode.HALF_UP):10.0 valueOfBigDecimal's scale:2 valueOfBigDecimal setScale(3):10.010 valueOfBigDecimal setScale(2):10.01 valueOfBigDecimal setScale(1):java.lang.ArithmeticException: Rounding necessary valueOfBigDecimal setScale(1, RoundingMode.HALF_UP):10.0 newStringBigDecimal's scale:2 newStringBigDecimal setScale(3):10.010 newStringBigDecimal setScale(2):10.01 newStringBigDecimal setScale(1):java.lang.ArithmeticException: Rounding necessary newStringBigDecimal setScale(1, RoundingMode.HALF_UP):10.0
2. 结果分析:string
经过运行结果咱们会发现两种状况:it
①经过new直接将double做为参数传入获得的值输出后并不等于原double值,传入string或valueOf方法获得的结果等于原值;io
事实上查看Java文档会发现有三种方式将double转为BigDecimal:二进制
1. new BigDecimal(double d);float
2. new BigDecimal(String s);
3.BigDecimal.valueOf(double d) ;
第一种是double的二进制形式的结果,因此BigDecimal的值并不必定为其原值,如上代码所示:10.0000000001转换后为10.0000000001000000082740370999090373516082763671875 ,
共有49位小数(不一样机器结果会不一样),
10.01转换后为10.0099999999999997868371792719699442386627197265625,
第二种和第三种结果相同,仍然为原值,由于第三种至关于先将double转为String(Double.toString(double))。
②同时咱们会发现,当设置结果小数位数小于当前位数时,若是未设置进位方式会抛出异常:java.lang.ArithmeticException: Rounding necessary,提示咱们进位方式必须,当咱们设置四舍五入后便可,其余方式可查看RoundingMode枚举类。
3、结论:
经过上述分析,咱们能够看出当对BigDecimal的值进位时需指定进位方式,不然会发生java.lang.ArithmeticException: Rounding necessary。