浮点数的等值判断
浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 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);