案例

​​

浮点数之间的判断

一、【强制】浮点数之间的等值判断,基本数据类型不能用==​来比较,包装数据类型不能用equals来判断

说明:浮点数采用“尾数+阶码”的编码格式,类似于科学计数法“有效数字+指数”的表示方式。二进制无法精确表示大部分的进制小数,具体原理参考《码出高效》

反例:

float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
if(a == b) {
	// 预期进入此代码块,但实际上a==b的结果为false
}
Float x = Float.valueOf(a);
Float y = Float.valueOf(b);
if(x.equals(y)) {
	// 预期进入此代码块,但实际上equals的结果为false
}

正确操作:

  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("true");
    }
    
  1. 使用BigDecimal来定义值,再进行浮点数之间的运算。

    BigDecimal a = new BigDecimal("1.0");
    BigDecimal b = new BigDecimal("0.9");
    BigDecimal c = new BigDecimal("0.8");
    BigDecimal x = new a.subtract(b);
    BigDecimal y = new b.subtract(c);
    if(x.equals(y)){
    	System.out.println("true");
    }
    

二、【强制】禁止使用构造方法BigDecimal(double)的方式把double值转换为BigDecimal对象。

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

如:BigDecimal g= new BigDecimal(0.1f); 实际的存储值为:0.10000000149

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

BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal.valueOf(0.1);