在 Java 中,float(以及 double)浮点数不精确,根本原因是:它们采用 IEEE 754 二进制浮点数标准,而很多十进制小数无法用有限二进制小数精确表示。
下面分层次说明。
计算机底层使用二进制(0 和 1)。
十进制小数转二进制的方法是「乘 2 取整」,例如:
0.1(十进制)
= 0.00011001100110011...(二进制,无限循环)
但 float 只有 32 位,double 只有 64 位,只能保存有限位,因此必须截断或四舍五入。
✅ 结果:存储的值已经不是 0.1,而是一个极接近 0.1 的近似值
float 共 32 位:
1 位符号位
8 位指数位
23 位尾数位
它表示的是:
(-1)^符号 × 1.xxx × 2^指数
⚠️ 这种结构天生适合 2 的幂(如 0.5、0.25),但不适合 10 的幂(如 0.1、0.3)
System.out.println(0.1f + 0.2f);
// 输出:0.30000001192092896
原因:
0.1f 存的是近似值0.2f 也是近似值因为:
| 类型 | 位数 | 精度 | 适用 |
|---|---|---|---|
| float | 32 | ~6–7 位十进制 | 节省内存 |
| double | 64 | ~15–16 位十进制 | 更常用 |
⚠️ double 也不是“精确”,只是误差更小
BigDecimal(推荐)BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 0.3
⚠️ 不要用 new BigDecimal(0.1),仍不精确
BigDecimal不要直接 ==
if (Math.abs(a - b) < 1e-6) { ... }
Java 的 float 不精确,是因为它用有限二进制位去近似表示十进制小数,而很多十进制小数在二进制中是无限循环的。
如果你愿意,我也可以:
float / double / BigDecimal0.1 + 0.2 ≠ 0.3 的底层计算步骤免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。