浮点数的陷阱:你以为的 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 的使用误区、格式化的陷阱、判等的误解……这一切都可能让你写下看似完美的代码,却埋下金额出错的隐雷。

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

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

你可能感兴趣的:(开发语言,互联网实用指南分享)