浮点数的陷阱:你以为的 0.1 + 0.2其实不是 0.3,BigDecimal你真的用对了吗?

目录

一、引子:看似简单的加法为何出错?

(一)10% + 20% = 0.3?计算器为何不讲理?

0.1 + 0.2 ≠ 0.3 的反直觉现实

(二)从“理所当然”到“错愕”的转变

二、误差之源:浮点数精度陷阱

(一)为什么 0.1 不能被精确表示?

类比:1/3 在十进制中无法精确表示

(二)Java 中的 double 是如何存储的?(IEEE 754 简介)

举个例子:double d = 0.1;

(三)几个典型的反直觉计算案例

✅ 案例 1:加法误差

✅ 案例 2:金额加法

✅ 案例 3:金额减法

(四)小误差,大问题:一分钱的损失如何变成 30 万?

📌 背景

📌 问题

📌 教训

小结:你眼中的“0.1”,计算机眼中可能是“0.10000000000000001”

三、第一道防线:BigDecimal 的正确使用

(一)BigDecimal 真能解决一切吗?

(二)new BigDecimal(double) 的巨大坑

📌 问题演示

📌 背后机制

📌 推荐做法

✅ 正确性对比

(三)推荐构造方式及其区别

(四)scale 和 precision 的影响及副作用(通过实际乘法案例分析)

✅ 基本概念

📌 真实案例:乘法未指定舍入模式时抛出异常

📌 另一种误用:精度丢失

(五)小结:BigDecimal 很强,但你得用对方法

四、第二道防线:浮点数的格式化与舍入

(一)String.format 为何得出奇怪的 3.4 和 3.3?

📌 原因剖析

📌 银行家舍入模式解释(HALF_EVEN)

(二)RoundingMode 的各种模式与默认行为

(三)DecimalFormat vs BigDecimal:谁才靠谱?

✅ DecimalFormat:适合展示层(String)

✅ BigDecimal:适合运算和持久化

✅ 实战建议

推荐格式化方式:BigDecimal + setScale + RoundingMode

(四)小结:展示不等于计算,格式不等于精度

五、判等陷阱:float/double/BigDecimal 的“==”误会

(一)为什么 amount1 - amount2 == 1.05 为 false?

📌 原因解析

⚠️ 危险的误判后果

(二)equals() 和 compareTo() 的区别

📌 为什么 equals 不安全?

✅ 推荐:使用 compareTo() == 0 判等

(三)浮点判等的三种思路(场景实用指南)

✅ 思路一:绝对误差阈值(适用于 double)

✅ 思路二:BigDecimal 精确判等(适用于金额)

✅ 思路三:compareTo == 0 判等

(四)实战踩坑示例:开发者 A 的误判之痛

(五)小结:判等,是浮点世界最后一道坑

六、总结与建议:写给开发者的避坑手册

(一)🧠 浮点数开发四步法:从思考到落地

1. 存储方式选对了吗?

2. 运算方式可靠了吗?

3. 格式化环节安全了吗?

4. 比较操作正确了吗?

(二)✅ 最佳实践 Checklist:金融系统浮点数安全用法

(三)📌 什么时候可以“不那么较真”?

(四)💡 技术背后的意识:你是在建一个“可信赖的系统”

(五)🎯 最后的金句总结(送给每一位开发者)

📘 全文回顾


干货分享,感谢您的阅读!

“就加了个 0.1 + 0.2,怎么就不是 0.3 了?”
“同一个接口,线上调账 1 分,结果整整少了 300,000 元?”

听上去像是段子,但这类事故在金融系统、支付平台、清结算逻辑中并不罕见

在程序世界里,0.1 + 0.2 != 0.3 并不是一个 bug,而是数学与计算机底层的差异冲突。浮点数的本质、Java 中 double 的局限、BigDecimal 的使用误区、格式化的陷阱、判等的误解……这一切都可能让你写下看似完美的代码,却埋下金额出错的隐雷。

这篇文章,将带你逐步揭开

评论 189
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张彦峰ZYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值