<p>应使用误差阈值(epsilon)判断浮点数“近似相等”,如Math.abs(a - b) < 1e-9;临界值判断需容错偏移,如x >= 1.0改为x >= 1.0 - 1e-10;金额等确定性场景必须用BigDecimal字符串构造并调用compareTo()。</p>

Java 中浮点数(float、double)由于底层采用 IEEE 754 二进制表示,很多十进制小数无法精确存储,导致计算结果存在微小误差。直接用 == 判断两个浮点数是否“相等”,或用 >/< 做临界值判断,很容易出错。
用误差范围(epsilon)代替精确相等判断
不比较是否完全相等,而是判断两数之差是否小于一个极小的容忍阈值(如 1e-6 或 1e-9):
-
double a = 0.1 + 0.2;实际值约为0.30000000000000004,不是严格等于0.3 - 正确写法:
Math.abs(a - 0.3) < 1e-9 - 阈值选多大取决于业务场景:科学计算常用
1e-15(double),金融或 UI 显示常用1e-6~1e-3
对临界值判断做“容错偏移”
比如判断某个值是否“大于等于 1.0”,但因误差可能算出来是 0.9999999999999999,导致逻辑跳过:
- 避免:
if (x >= 1.0) - 稳妥写法:
if (x >= 1.0 - 1e-10)(把边界往安全方向“松一点”) - 同理,
x <= 0.0可改为x <= 1e-10,避免负向微误差漏判
该用 BigDecimal 的地方别硬扛 float/double
涉及金额、计数、配置阈值等**要求逻辑确定性**的场景,必须用 BigDecimal:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 构造时用字符串,避免 double 字面量污染:
new BigDecimal("0.1").add(new BigDecimal("0.2"))→ 精确得0.3 - 比较用
compareTo()(返回 -1/0/1),不用equals()(会比较 scale) - 注意:
BigDecimal运算稍重,非必要不替代所有浮点场景,但关键判断处不能妥协
提前归一化或四舍五入再比较(谨慎使用)
如果业务允许一定精度损失,可统一保留小数位后比较:
-
double rounded = Math.round(value * 100.0) / 100.0;(保留两位小数) - 再用
==或Math.abs()判断,但要注意round本身也有 long 溢出风险 - 更安全的是用
BigDecimal的setScale(2, RoundingMode.HALF_UP)
核心原则:浮点数适合近似计算和性能敏感场景;条件判断尤其是分支逻辑,必须主动防御精度误差。选对方法比“碰运气”可靠得多。

















