BigDecimal的各种坑 Non-terminating decimal expansion

来源:互联网 发布:蜂窝移动数据 空的 编辑:程序博客网 时间:2024/05/17 09:21

总结下这些天遇到的关于 BigDecimal的问题,有不完善的地方,大家一起完善哈!

 

  1. BigDecimal的divide方法进行除法时当不整除,出现无限循环小数

    • 报的异常:
      java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    • 场景再现:
      @Testpublic void test1() {  BigDecimal num1 = new BigDecimal("10"); BigDecimal num2 = new BigDecimal("3"); BigDecimal num3 = num1.divide(num2);}
    • 解决方案:
      使用divide的重载方法
      BigDecimal.divide(BigDecimal divisor, int scale, RoundingMode roundingMode) ;
           scale为小数位数;

           roundingMode为小数模式;

                   ROUND_CEILING
                   如果 BigDecimal 是正的,则做 ROUND_UP 操作;如果为负,则做 ROUND_DOWN 操作。
                   ROUND_DOWN
                   从不在舍弃(即截断)的小数之前增加数字。
                   ROUND_FLOOR
                   如果 BigDecimal 为正,则作 ROUND_UP ;如果为负,则作 ROUND_DOWN 。
                   ROUND_HALF_DOWN
                   若舍弃部分> .5,则作 ROUND_UP;否则,作 ROUND_DOWN 。
                   ROUND_HALF_EVEN
                   如果舍弃部分左边的数字为奇数,则作 ROUND_HALF_UP ;如果它为偶数,则作 ROUND_HALF_DOWN 。
                   ROUND_HALF_UP
                   若舍弃部分>=.5,则作 ROUND_UP ;否则,作 ROUND_DOWN 。
                   ROUND_UNNECESSARY
                   该“伪舍入模式”实际是指明所要求的操作必须是精确的,,因此不需要舍入操作。
                   ROUND_UP
                   总是在非 0 舍弃小数(即截断)之前增加数字。
      写成如下便可通过

      BigDecimal num3 = num1.divide(num2, 10, BigDecimal.ROUND_HALF_DOWN);

       

  2. 创建BigDecimal对象,出现精度问题

    • 问题描述:
      新建一个BigDecimal的类的时候,构造函数是float或者double的时候,会出现精度问题
    • 场景再现
      @Testpublic void test2() {  System.out.println(new BigDecimal("2.3")); System.out.println(new BigDecimal(2.3));}

      输出的结果是

      2.3
      2.29999999999999982236431605997495353221893310546875

    • 解决方案
      尽量不要传float和double类型的,可以把float或者double先转换为String, 然后再构造BigDecimal,如:

      @Testpublic void test3() {double d = 2.3; String ds = String.valueOf(d); System.out.println(new BigDecimal(ds));}
  3. 总结:

  • 构造BigDecimal时尽量避免传递float和double类型,有可能话,尽量使用intString类型。
  • 做乘除计算时,一定要设置精度和保留小数点位数,除法运算时要注意除数为零的可能性。
  • BigDecimal计算时,单独放到try catch
0 0
原创粉丝点击