返回

0.1 + 0.2 不等于 0.3 的秘密:浮点数的浮华

前端

JavaScript 浮点数之迷:0.1 + 0.2 为什么不等于 0.3?

“0.1 + 0.2 = ?” 这个问题,你要是问小学生,他也许会立马告诉你 0.3。但是在计算机的世界里就没有这么简单了,做为一名程序开发者在你面试时如果有人这样问你,小心陷阱喽! 你可能在哪里见过 “0.1 + 0.2 = 0.30000000000000004” 但是知道为什么会出现这种情况吗?

浮点数的本质

浮点数是一种计算机用来表示实数的近似值。它们使用科学计数法,其中数字由基数(通常为 2)的幂缩放。例如,浮点数 1.23 可以表示为 1.23 x 10^0,其中 1.23 是尾数,0 是指数。

浮点数的精度是有限的,因为它们只能存储有限数量的位。这会导致舍入误差,尤其是在进行加法和减法运算时。

IEEE 754 标准

IEEE 754 是一个国际标准,定义了浮点数在计算机系统中的表示和运算方式。该标准规定了两种常见的浮点数格式:单精度和双精度。

单精度浮点数使用 32 位来表示,其中 1 位用于符号位,8 位用于指数,23 位用于尾数。双精度浮点数使用 64 位来表示,其中 1 位用于符号位,11 位用于指数,52 位用于尾数。

0.1 + 0.2 的问题

当我们尝试在计算机中表示十进制数 0.1 和 0.2 时,就会出现问题。这是因为十进制小数不能总是精确地表示为二进制浮点数。例如,0.1 在二进制中表示为 0.0001100110011001100110011001100...,这是一个无限不循环小数。

计算机使用一种称为舍入的技术来处理这种情况。舍入意味着将数字四舍五入到最接近的可表示浮点数。对于 0.1,计算机将其四舍五入为 0.10000000149011612,这是最接近的单精度浮点数表示。

同样的,0.2 在二进制中表示为 0.001100110011001100110011001100...,计算机将其四舍五入为 0.20000000298023224。

现在,当我们尝试对这两个浮点数求和时,计算机将它们相加,得到 0.30000000447034835。然而,由于舍入误差,这个值并不是 0.3 的精确表示。

避免浮点数误差

避免浮点数误差的最佳方法是使用整数运算或使用支持任意精度的库,例如 std::fixed_point。此外,在比较浮点数时,应该使用容差而不是直接相等比较。

结论

浮点数在计算机中表示实数时非常有用,但了解它们的局限性非常重要。舍入误差可能会导致意外的结果,因此在使用浮点数时应小心谨慎。