浮点数比较当中的精度误差问题及解决

问题描述

在使用浮点型数据时,通常需要考虑到浮点数的误差问题,有些看似相等的操作,实际上计算机执行起来可能并不是我们想象中的样子。

比如:判断两个Double类型的数据相等该怎么写?

刚学编程时,我想应该是这样:

double x = 0.3;
double y = 0.3;
System.out.println(x == y);

确实也没错

但是当换成 x=0.1+0.2 时,就出问题了,请看JPG

可以看到,当x的值换成 0.1 + 0.2 时,结果就不符合我们预期了,这里就涉及到了浮点数计算当中存在的精度误差问题。

使用包装类的equals也是同理,可以看到,0.1+0.2的计算结果并不是0.3,一串0后边多出来的就是浮点数计算的误差,这是问题的关键。

注:包装类对象为引用数据类型,equals方法比较的是引用对象内的值。

问题分析

包装类的equals方法默认比较的是值的精确性,而不是近似性。因此,在比较两个Double对象的值时,可能会受到浮点数计算的精度问题的影响。

这里的a和b都是Double对象,通过equals方法比较它们的值,结果为false,这是因为0.1+0.2的结果在double类型下实际上是一个近似值0.30000000000000004,而不是精确的0.3,所以值比较不相等。

问题解决

在遇到这种我们认为是相等,但却由于浮点数误差而造成的不等时,我们就需要通过别的办法来处理这个计算误差,使它们的结果变为相等。

常见的办法是通过比较两数之差的绝对值是否小于某一个很小的数(自定义),让它们的比较允许有一个很小的误差,符合误差范围时,即判断它们相等,以这种方式来处理浮点数计算误差。

        //基本数据类型
        double x = 0.1 + 0.2;
        double y = 0.3;
        double z = 0.3;
        System.out.println(x == y);
        System.out.println(y == z);
        System.out.println("========");

        //包装类
        //比较两个Double类型的值
        Double a = 0.1 + 0.2;
        Double b = 0.3;

        System.out.println("a="+a+",b="+b);

        // 方法一:使用equals方法判断
        if (a.equals(b)) {
            System.out.println("a 等于 b");
        } else {
            System.out.println("a 不等于 b");
        }
        System.out.println("========");

        // 方法二:比较差的绝对值是否小于一个很小的数
        double epsilon = 0.0000001; // 定义一个很小的数,即误差范围
        if (Math.abs(a - b) < epsilon) {
            System.out.println("误差范围内,a 等于 b");
        } else {
            System.out.println("a 不等于 b");
        }

小结

浮点型数据比较方式:

(1)"==":使用于基本数据类型,用于判断两个值是否相等,作用于浮点型数据时,可能会存在误差。使用在包装类引用数据时,比较的是地址。

(2)"equals":使用与包装类对象的值比较,比较的是两个对象的精确值,当出现精度误差时,认为二者不等。

(3)"Math.abs(a - b) < epsilon":比较绝对值误差:可使用于包装类也可使用于基本数据类型,定义一个误差范围,计算差值的绝对值,判断二者是否近似相等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值