java浮点数比较不能用==,因二进制无法精确表示多数十进制小数;应采用epsilon阈值法、bigdecimal精确比较或整数缩放法,并规避常见陷阱。

Java 中浮点数比较不能直接用 ==,因为 float 和 double 的二进制存储本质决定了它们无法精确表示多数十进制小数(如 0.1、0.3),运算结果天然带舍入误差。比较时若不处理,0.1 + 0.2 == 0.3 会返回 false。
用误差阈值(epsilon)判断近似相等
适用于科学计算、物理模拟、图形渲染等允许微小偏差的场景。
- 定义一个足够小的正数
epsilon,例如1e-10(普通计算)、1e-6(图形渲染) - 用
Math.abs(a - b) 替代 <code>a == b - 当两数数量级差异大时,改用相对误差:
Math.abs(a - b) / Math.max(Math.abs(a), Math.abs(b))
用 BigDecimal 进行精确比较
适用于金融、计费、配置校验等要求严格相等的业务场景。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 构造时必须用字符串:
new BigDecimal("0.1"),而非new BigDecimal(0.1)(后者会把 double 的误差带进来) - 比较相等性用
.compareTo()方法:bd1.compareTo(bd2) == 0 - 避免使用
.equals():它会同时比较数值和标度(scale),"1.0"和"1.00"被视为不等
用整数缩放后比较
适用于单位明确、可预设精度的场景,比如金额(元→分)、温度(℃→厘度)、时间(秒→毫秒)。
- 将原始值乘以固定倍数转为
long或BigInteger,全程整数运算 - 转换时用
Math.round(value * scale)防止截断误差,不要直接强转 - 比较直接用
==或.equals(),无精度干扰
避免常见陷阱
很多“看似正确”的写法其实仍会出错。
- 不用
Double.toString(d)再构造BigDecimal:虽然比直接传 double 好,但Double.toString本身有舍入规则,推荐用BigDecimal.valueOf(d)(内部做了安全转换) - 不混用 float/double 比较:
float f = 0.1f; double d = 0.1;,再比较f == d极易因隐式提升失准 - 不依赖
Math.round()后直接比较 double:它只解决显示问题,未消除底层误差,仍需配合 epsilon 或转 BigDecimal
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










