zoukankan      html  css  js  c++  java
  • BigDecimal 类的使用

    BigDecimal 类的使用

    1、使用 BigDecimal 的原因

      由于需要计算金额,所有需要高精度计算,所有需要使用 BigDecimal 类。
    BigDecimal能够精确的表示一个小数,常用于商业和科学计算;float,double不能精确的表示一个小数。

    2、常用方法

    2.1 加法(add)

      分别用两种不同的数据类型(long 和 string)创建 BigDecimal 对象;

    import java.math.BigDecimal;
    
    public class BigDecimalTest {
        /**
         * 使用BigDecimal,参数类型是double类型,计算还是不精确
         */
        @Test
        public void testAdd1(){
            BigDecimal b1 = new BigDecimal(0.05);
            BigDecimal b2 = new BigDecimal(0.01);
            System.out.println(b1.add(b2));  
            //输出:0.06000000000000000298372437868010820238851010799407958984375
        }
    
        /**
         * 使用BigDecimal,参数类型是String类型,计算结果精确
         */
        @Test
        public void testAdd2(){
            BigDecimal b1 = new BigDecimal("0.05");
            BigDecimal b2 = new BigDecimal("0.01");
            System.out.println(b1.add(b2));  
            //输出:0.06
        }
    }
    

      从上面的结果可以看出使用 string 类型的才能得到精确的计算结果。所有在计算金额时注意使用 string 类型创建对象。

    2.2 减法(subtract)

    import java.math.BigDecimal;
    
    public class BigDecimalTest {
        /**
         * 测试减法 参数类型是double类型,计算还是不精确
         */
        @Test
        public void testSubtract1(){
            BigDecimal b1 = new BigDecimal(0.05);
            BigDecimal b2 = new BigDecimal(0.01);
            System.out.println(b1.subtract(b2));
            //输出:0.04000000000000000256739074444567449972964823246002197265625
        }
    
        /**
         * 测试减法,参数类型是String类型,计算结果精确
         */
        @Test
        public void testSubtract2(){
            BigDecimal b1 = new BigDecimal("0.05");
            BigDecimal b2 = new BigDecimal("0.01");
            System.out.println(b1.subtract(b2));
            //输出:0.04
        }
    }
    

    2.3 乘法(multiply)

    import java.math.BigDecimal;
    
    public class BigDecimalTest {
        /**
         * 测试乘法 参数类型是double类型,计算还是不精确
         */
        @Test
        public void testMultiply1(){
            BigDecimal b1 = new BigDecimal(0.05);
            BigDecimal b2 = new BigDecimal(0.01);
            System.out.println(b1.multiply(b2));
            //输出:0.0005000000000000000381639164714897566548413219067927041589808827754781955614304944646164585719816386699676513671875
        }
    
        /**
         * 测试乘法,参数类型是String类型,计算结果精确
         */
        @Test
        public void testMultiply2(){
            BigDecimal b1 = new BigDecimal("0.05");
            BigDecimal b2 = new BigDecimal("0.01");
            System.out.println(b1.multiply(b2));
            //输出:0.0005
        }
    }
    

    2.4 除法(divide)

    2.4.1 除不尽,报错

      由于10/3除不尽,商是无限小数,所以报错;

      Non-terminating decimal expansion; no exact representable decimal result.

    import java.math.BigDecimal;
    
    public class BigDecimalTest {
       /**
         * 测试除法 参数类型是double类型
         */
        @Test
        public void testDivide1(){
            BigDecimal b1 = new BigDecimal(0.1);
            BigDecimal b2 = new BigDecimal(0.03);
            System.out.println(b1.divide(b2));
            //报错 java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
        }
    
        /**
         * 测试除法,参数类型是String类型
         */
        @Test
        public void testDivide2(){
            BigDecimal b1 = new BigDecimal("0.1");
            BigDecimal b2 = new BigDecimal("0.03");
            System.out.println(b1.divide(b2));
            //报错 java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
        }
    }
    
    2.4.2 解决办法

      其实devide的函数定义如下:

    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,ROUND_HALF_DOWN);

    import java.math.BigDecimal;
    
    public class BigDecimalTest {
        /**
         * 测试除法 参数类型是double类型
         */
        @Test
        public void testDivide3(){
            BigDecimal b1 = new BigDecimal(0.1);
            BigDecimal b2 = new BigDecimal(0.03);
            System.out.println(b1.divide(b2, 10, ROUND_HALF_DOWN));
            //输出:3.3333333333
        }
    
        /**
         * 测试除法,参数类型是String类型
         */
        @Test
        public void testDivide4(){
            BigDecimal b1 = new BigDecimal("0.1");
            BigDecimal b2 = new BigDecimal("0.03");
            System.out.println(b1.divide(b2, 10, ROUND_HALF_DOWN));
            //输出:3.3333333333
        }
    

    3、小结

    1. 使用 string 类型创建 BigDecimal 对象来进行精确计算;
    2. 进行除法计算时,需要添加参数(scale)小数位数和(roundingMode)小数模式;避免出现除不尽报错的现象;
  • 相关阅读:
    EF-一对一关系
    EF-生成迁移版本
    打包、压缩指令
    gut pull 拉取出错
    nohup的使用方法
    fopen打开文件出错
    实现多线程下载图片到本地③
    实现单线程下载图片到本地②
    服务器重装系统后终端登录不上去
    简单实现图片抓取下载到本地①
  • 原文地址:https://www.cnblogs.com/zt19994/p/9509211.html
Copyright © 2011-2022 走看看