0.1 + 0.2 到底等不等于 0.3 ?

496 阅读3分钟

前言

面试官:0.1 + 0.2 等于多少?

我:image.png

我:反正不等于0.3


一、JavaScript 中的浮点数

在 JavaScript 中,所有数字(无论是整数还是浮点数)都是以 双精度浮点数(double-precision floating-point format) 来存储的。这是根据 IEEE 754 标准定义的,意味着它遵循与其他编程语言类似的浮点数表示规则。

然而,双精度浮点数在表示某些十进制数时也存在精度问题。就像我们在前面提到的 0.10.2,这些数字在二进制浮点数中无法精确表示。

二、为什么 0.1 + 0.2 != 0.3

0.10.2 在二进制浮点数中无法被精确表示,它们是循环小数。具体来说:

  • 0.1 在二进制中是:0.00011001100110011001100110011...,它是一个无限循环小数。
  • 0.2 也在二进制中是一个无法精确表示的值:0.00110011001100110011001100110...

当你执行 0.1 + 0.2 时,计算机在存储这些值时会做出一定的舍入,从而导致最终的计算结果不等于你期望的 0.3

三、JS 示例

我们可以通过代码在 JavaScript 中验证这个现象。

// 浮点数加法
let result = 0.1 + 0.2;

console.log(result);               // 输出:0.30000000000000004
console.log(result === 0.3);       // 输出:false

运行结果:

0.1 + 0.2 = 0.30000000000000004
0.1 + 0.2 == 0.3? false

image.png

如你所见,0.1 + 0.2 结果是 0.30000000000000004,它并不等于 0.3,这就是因为浮点数运算的精度问题。

四、解决浮点数误差

为了避免浮点数误差,JavaScript 中有几种常见的方法:

1. 通过四舍五入来处理误差

我们可以通过四舍五入的方式将结果精确到指定的小数位。比如,如果你想让计算结果精确到小数点后 2 位,可以这样做:

let result = 0.1 + 0.2;
result = Math.round(result * 100) / 100;

console.log(result);               // 输出:0.3
console.log(result === 0.3);       // 输出:true

2. 使用 Number.toFixed() 方法

toFixed() 方法可以将浮点数转换为固定小数位的字符串,这样就可以避免计算中出现的精度误差。

let result = 0.1 + 0.2;
result = result.toFixed(2);  // 将结果格式化为2位小数

console.log(result);          // 输出:0.30
console.log(parseFloat(result) === 0.3);  // 输出:true

注意:toFixed() 返回的是字符串类型,因此你可能需要使用 parseFloat()parseInt() 将其转换回数字进行比较。

3. 通过乘法转换为整数

与其他编程语言类似,你也可以通过将浮点数乘以一个常数(比如 100)转换为整数进行计算,最后再除以这个常数恢复为小数。这种方法通常适用于货币等需要精确计算小数的场景。

let result = (0.1 * 100 + 0.2 * 100) / 100;

console.log(result);               // 输出:0.3
console.log(result === 0.3);       // 输出:true

五、总结

在 JavaScript 中,0.1 + 0.2 != 0.3 是因为浮点数的存储方式导致精度误差。浮点数无法精确表示某些十进制数(例如 0.1 和 0.2),因此加法运算的结果会偏离期望值。

你可以通过以下方法来避免或修正这种问题:

  • 使用 Math.round() 来四舍五入到特定的小数位。
  • 使用 toFixed() 来将结果格式化为固定的小数位。
  • 将浮点数转为整数进行计算,再恢复小数。

这些方法可以有效地减小误差,确保结果符合预期。

现在可以跟面试官大声说出来0.1 + 0.2 等于多少了

没错,等于0.3(15个0)4

Snipaste_2024-11-26_16-52-11.png