在 Java 中,float(以及 double)出现精度丢失,根本原因不是 Java 的问题,而是 浮点数本身的二进制表示方式决定的。下面从原理到例子讲清楚。
我们日常使用的是十进制小数,而计算机只能存储二进制(0 和 1)。
有些十进制小数 无法用有限位的二进制精确表示。
例如:
十进制 0.1
二进制 = 0.0001100110011001100110011...(无限循环)
而 float 只有 32 位,double 只有 64 位,必须“截断”,于是就产生了误差。
Java 的 float 遵循 IEEE 754 标准:
float(32位):
符号位 1 位
指数位 8 位
尾数位 23 位
意味着:
一旦超出这个精度,就会“丢精度”。
float a = 0.1f;
float b = 0.2f;
System.out.println(a + b);
输出:
0.30000001192092896
原因:
0.1 和 0.2 在二进制中是无限循环小数float x = 1.0f / 3;
System.out.println(x * 3 == 1.0f); // false
因为:
1.0 / 3 ≈ 0.33333334
×3 ≈ 1.0000001
整数(如 int)在二进制中是精确可表示的:
10 → 1010 ✅
但很多小数在二进制中是无限循环的:
0.1 → 0.000110011... ❌
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) // 仍然有误差
double(误差更小,但不是精准)double d = 0.1 + 0.2;
== 比较浮点数if (Math.abs(a - b) < 1e-6) { ... }
Float 精度丢失,是因为很多十进制小数在二进制中是无限循环的,而 float 位数有限,只能近似存储。
如果你愿意,我也可以帮你画 0.1 的二进制转换过程图,或者对比 float / double / BigDecimal 的适用场景。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。