BigDecimal造成的精度问题
案例

浮点数之间的判断
一、【强制】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用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
}
正确操作:
指定一个差值范围,两个浮点数的差值在此范围内,即认为这两个浮点数相等。
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"); }
使用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);
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Dominic
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

