这是个很好的问题,核心其实在于 BigDecimal 的“整数/小数”内部表示方式 以及 它不使用二进制浮点。
我们常见的:
floatdouble都是 IEEE 754 二进制浮点数:
用“二进制”去逼近十进制小数
例如:
0.1 (十进制)
= 0.0001100110011... (二进制,无限循环)
所以 double 永远无法精确表示 0.1,只能近似。
BigDecimal 内部大概是这样的结构(简化):
BigInteger unscaledValue; // 未缩放的整数
int scale; // 小数位数
例如:
new BigDecimal("12.34")
内部表示为:
unscaledValue = 1234
scale = 2
也就是说:
BigDecimal 实际上存的是一个“整数”,只是告诉你小数点在哪
BigInteger 的特点是:
所以:
1234 是整数 → 绝对精确
12345678901234567890123456789 → 也绝对精确
只要:
double 构造器✅ BigDecimal 就能 100% 精确表示
因为:
例如:
12.34 + 5.6
→ 1234/100 + 560/100
→ (1234 + 560) / 100
→ 1794 / 100
= 17.94
全程没有“近似”。
⚠️ 只有一种情况:你用了 double 构造
new BigDecimal(0.1) // ❌ 不精确
因为:
0.1 在 double 里已经是近似值✅ 正确写法:
new BigDecimal("0.1")
BigDecimal 精确,是因为它把十进制数变成“任意长度整数 + 小数点位置”,而不是用二进制去逼近。
如果你愿意,我也可以画一张 double vs BigDecimal 的内存对比图,或者讲讲它内部是怎么做除法的。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。