BigDecimal浮点数处理(阿里Java开发手册规范)


关于浮点数处理问题,BigDecimal的精度问题,BigDecimal增删查改操作,参考阿里巴巴Java开发手册规范处理


浮点数比较问题

浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用equals来判断。

问题:可以发现这两句都没有执行

public static void main(String[] args) {
  float a = 1.0F - 0.9F;
  float b = 0.9F - 0.8F;
  if (a == b) {
    System.out.println("未执行");
  }
  Float x = Float.valueOf(a);
  Float y = Float.valueOf(b);
  if (x.equals(y)) {
  	System.out.println("未执行");
  }
}

这里阿里巴巴JAVA开发手册 [^1]中也有提到

image-20210715142952399

解决

  1. 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的

    float a =1.0F-0.9F;
    float b =0.9F-0.8F;
    float diff =1e-6F;
    if(Math.abs(a -b)<diff){
      System.out.println("执行");
    }
    
  2. 使用BigDecimal来定义值,再进行浮点数的运算操作(推荐使用

    BigDecimal a = new BigDecimal("1.0");
    BigDecimal b = new BigDecimal("0.9");
    BigDecimal c = new BigDecimal("0.8");
    BigDecimal x = a.subtract(b);
    BigDecimal y = b.subtract(c);
    if (x.compareTo(y) == 0) {
    	System.out.println("执行");
    }
    

    比较时候使用compareTo进行比较,equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度,使用下面代码进行测试发现只有compareTo执行了。

    BigDecimal x = new BigDecimal("0.1");
    BigDecimal y = new BigDecimal("0.10");
    if(x.equals(y)) {
    	System.out.println("未执行!");
    }
    if(x.compareTo(y) == 0) {
    	System.out.println("执行!");
    }
    

BigDecimal初始化

初始化时应该使用字符串的形式进行初始化定义,对比一下他们的区别

BigDecimal a = new BigDecimal(0.1F); 
BigDecimal b = new BigDecimal("0.1"); 
System.out.println(a);
System.out.println(b); 
image-20210715144946836

两种方式定义的值不一样,BigDecimal(double)存在精度损失风险,这里阿里巴巴Java开发手册 [^1]中也有提及

image-20210715145241058

BigDecimal增删查改操作

    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.123");
        BigDecimal b = new BigDecimal("0.987");
        BigDecimal c = new BigDecimal("-0.555");

        // 加
        BigDecimal add = a.add(b);
        // 减
        BigDecimal subtract = a.subtract(b);
        // 乘
        BigDecimal multiply = a.multiply(b);
        // 除,设置保留的小数点位数与四舍五入
        BigDecimal divide = a.divide(b, 20, BigDecimal.ROUND_HALF_UP);
        // 绝对值
        BigDecimal abs = c.abs();

        System.out.println(add);
        System.out.println(subtract);
        System.out.println(multiply);
        System.out.println(divide);
        System.out.println(abs);
    }

除法中的第二个参数是设置保留的小数点位数,第三个参数是设置如何进行四舍五入操作,阅读源码可知就是我们的平时使用的大于等于0.5时候就进一位。

image-20210715151451175

运行结果

image-20210715151042861

BigDecimal还有一些其它操作,可以去操作尝试下

阿里JAVA开发手册地址

手册阿里云盘链接:https://www.aliyundrive.com/s/MEtW4t5DdGh


版权声明:本文为weixin_44750617原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。