• 第二章 Java浮点数精确计算


    1、实际意义

    在实际开发中,如果需要进行float或double的精确计算(尤其是财务计算),直接使用float或double是不行的(具体的例子看下边的代码的main方法的测试结果),需要使用BigDecimal。

    2、代码

    package com.xxx.util;
    
    import java.math.BigDecimal;
    
    /**
     * 浮点数精准算法
     */
    public class BigDecimalArithUtil {
    
        private static final int DIV_SCALE = 10;//除法精度(除不尽时保留10为小数)
        
        /** 小数精确加法  */
        public static double add(double d1,double d2)
        {
            BigDecimal bd1 = BigDecimal.valueOf(d1);
            BigDecimal bd2 = BigDecimal.valueOf(d2);
            return bd1.add(bd2).doubleValue();
        }
        
        /** 小数精确减法  */
        public static double sub(double d1,double d2)
        {
            BigDecimal bd1 = BigDecimal.valueOf(d1);
            BigDecimal bd2 = BigDecimal.valueOf(d2);
            return bd1.subtract(bd2).doubleValue();
        }
        
        /** 小数精确乘法  */
        public static double mul(double d1,double d2)
        {
            BigDecimal bd1 = BigDecimal.valueOf(d1);
            BigDecimal bd2 = BigDecimal.valueOf(d2);
            return bd1.multiply(bd2).doubleValue();
        }
        
        /** 小数精确除法   */
        public static double div(double d1,double d2)
        {
            BigDecimal bd1 = BigDecimal.valueOf(d1);
            BigDecimal bd2 = BigDecimal.valueOf(d2);
            /*
             * 当除不尽时,以四舍五入的方式(关于除不尽后的值的处理方式有很多种)保留小数点后10位小数
             */
            return bd1.divide(bd2, DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        
        public static void main(String[] args)
        {
            //测试加法
            System.out.println("0.05+0.01="+BigDecimalArithUtil.add(0.05,0.01));
            System.out.println("0.05+0.01="+(0.05+0.01));
            //测试减法
            System.out.println("1.0-0.42="+BigDecimalArithUtil.sub(1.0,0.42));
            System.out.println("1.0-0.42="+(1.0-0.42));
            //测试乘法
            System.out.println("4.015*100="+BigDecimalArithUtil.mul(4.015,100));
            System.out.println("4.015*100="+(4.015*100));
            //测试除法
            System.out.println("123.3/100="+BigDecimalArithUtil.div(123.3,100));
            System.out.println("123.3/100="+(123.3/100));
        }
    
    }
    View Code

    3、注意点

    • 上边的程序我用的是BigDecimal.valueOf(double x)来将double型的x封装成BigDecimal,查看源码如下:
          /**
           * 注意:这通常是将double和float转换为一个BigDecimal的最好方式
           */
          public static BigDecimal valueOf(double val) {
              return new BigDecimal(Double.toString(val));
          }
      View Code

      在这里直接先将double转换为了String,然后使用如下构造方法再将String转换为BigDecimal

       public BigDecimal(String val)

      这是最好的做法。如果使用的是直接将double或float转换为BigDecimal的方式,也就是说使用的如下构造器,那么将可能得不到精确结果。(看注释)这一点可以用10.02*10.02来证明。

          /**
           * 注意:The results of this constructor can be somewhat unpredictable.
           * 该构造器的结果有时是不准确的
           */
          public BigDecimal(double val)
      View Code
    • 在实际使用中还可能使用int和long来进行浮点数的精确计算(具体做法:将浮点数先乘以相应的倍数转化为int(<=9位十进制数)或long(<=18位十进制数),计算之后再除以之前的倍数,得出结果),而且该种方式的性能会更高,具体的int、long和BigDecimal各自的使用看《Effective Java(第二版)》第48条。
    • 需要指出的是,在实际开发中,BigDecimal的性能差的问题基本可以忽略,是浮点数精确计算的首选,而且根据上一条来看,如果将浮点数转化后的整数大于18位的话,也必须用BigDecimal
  • 相关阅读:
    【ArcGIS 10.2新特性】ArcGIS 10.2将PostgreSQL原生数据发布为要素服务
    字节流,字符流 有什么区别
    java--模板方法模式
    hdu2829 四边形优化dp
    【ArcGIS 10.2新特性】ArcGIS 10.2 for Desktop 新特性(二)
    B/S架构 Web打印程序(Argox)
    poj 1611 The Suspects(并查集)
    microsoft visual studio遇到了问题,需要关闭
    [置顶] Windows显示驱动(WDDM)编程初步(2)
    Linux查看设置系统时区
  • 原文地址:https://www.cnblogs.com/java-zhao/p/5188280.html
Copyright © 2020-2023  润新知