你有没有遇到过这种情况:在写代码算钱的时候,0.1 加 0.2 居然不等于 0.3?明明是小学生都会的题,电脑却算错了。比如在 JavaScript 里跑这么一段:
console.log(0.1 + 0.2); // 输出 0.30000000000000004
看到这个结果,很多人第一反应是“我代码写错了?”其实不是,这是浮点数的锅。
为啥浮点数会不准?
计算机底层用的是二进制,而像 0.1 这样的十进制小数,在二进制里是无限循环的。就像 1/3 在十进制里是 0.333… 一样,0.1 在二进制里也得无限写下去才能精确表示。可内存是有限的,系统只能截断保存一个近似值。
当你做加法时,其实是两个近似值在算,结果自然还是近似,误差就这么悄悄混进来了。
不只是 JavaScript 的问题
有人以为这是 JavaScript 不靠谱,其实 Python、Java、C++ 都有这毛病。因为大家默认都用 IEEE 754 标准来存浮点数。这个标准效率高,但天生就带精度缺陷。
比如 Python 里:
print(0.1 + 0.2) # 输出 0.30000000000000004
一样的配方,熟悉的味道。
实际场景中可能出大事
平时算个网页上的数值,差那么一丁点无所谓。可要是做金融系统,比如账户余额、交易金额,累积下来可能就差出几毛甚至几块。用户发现“我的钱对不上”,客服就得背锅。
再比如做科学计算、传感器数据融合,误差层层叠加,最后结果可能完全不可信。
怎么绕过去?
最简单的办法:别用浮点数算钱。把金额转成“分”来存,全部用整数运算。比如 10.5 元存成 1050 分,加减乘除都用整数,完事再除回去。
另一种方法是用语言提供的高精度类型。比如 Python 的 Decimal 模块:
from decimal import Decimal
a = Decimal('0.1')
b = Decimal('0.2')
print(a + b) # 输出 0.3
注意这里必须传字符串,写成 Decimal(0.1) 就晚了,0.1 读进来就已经变味了。
JavaScript 也有类似库,比如 big.js 或 decimal.js,专门处理这种“看着简单其实坑爹”的计算。
别指望永远精确
说到底,浮点数就是用精度换效率。大多数场景没问题,但涉及钱、科学、控制等对精度敏感的地方,就得主动防着点。别等线上出问题再去翻日志。
下次看到 0.1 + 0.2 ≠ 0.3,别慌,也不是电脑坏了,它只是按规则办事——哪怕规则有点瑕疵。