浮点数应该怎么比较大小才是真的精确?

浮点数的等值判断

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

说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数。

反例:

    @Test
    public void test02() {
    
    
        float a = 1.0F - 0.9F;
        float b = 0.9F - 0.8F;
        System.out.println(a == b);

        Float x = Float.valueOf(a);
        Float y = Float.valueOf(b);
        System.out.println(x.equals(y));
    }

正例: 使用 BigDecimal 来定义值,再进行浮点数的运算操作。

    @Test
    public void test03() {
    
    
        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);
        System.out.println(x.compareTo(y));
    }

BigDecimal 的等值比较

BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。

说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度

    @Test
    public void test04() {
    
    
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("1.00");
        System.out.println(a.compareTo(b));
        // 0  代表相等
        System.out.println(a.equals(b));
        // false
    }

BigDecimal的构造

不要使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。

说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。

如:

扫描二维码关注公众号,回复: 13267340 查看本文章
BigDecimal g = new BigDecimal(0.1F); 

实际的存储值为:0.10000000149

正例:优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,此方法内部其实执行了 Double 的 toString,而 Double 的toString 按 double 的实际能表达的精度对尾数进行了截断。

BigDecimal recommend1 = new BigDecimal("0.1"); 
BigDecimal recommend2 = BigDecimal.valueOf(0.1);

猜你喜欢

转载自blog.csdn.net/GBS20200720/article/details/121334488