大厂面试题:0.1 + 0.2 != 0.3?

108 阅读2分钟

前言:一个令人困惑的现象

每个JavaScript开发者都曾遇到过这个"诡异"的现象:

console.log(0.1 + 0.2); // 输出:0.30000000000000004

这看起来像是一个bug,但实际上这是计算机科学中浮点数表示的必然结果。今天我们就来深入探讨这个现象背后的原理。

一、IEEE 754浮点数标准

JavaScript采用IEEE 754标准来表示数字,这种表示法有三个关键特点:

  1. 二进制表示 :所有数字最终都以二进制形式存储
  2. 有限精度 :64位双精度浮点数(1位符号,11位指数,52位小数)
  3. 科学计数法 :类似于1.xxx × 2^yyy的形式

二、为什么0.1无法精确表示?

0.1在二进制中是一个无限循环小数:

0.1 (十进制) = 0.0001100110011001100110011001100110011001100110011001101... (二进制)

由于计算机存储空间有限,必须对这个无限循环小数进行截断,导致精度丢失。

三、实际计算过程

让我们看看0.1 + 0.2的具体计算过程:

  1. 0.1被存储为:
0.1000000000000000055511151231257827021181583404541015625
  1. 0.2被存储为:
0.200000000000000011102230246251565404236316680908203125
  1. 两者相加得到:
0.3000000000000000444089209850062616169452667236328125

四、解决方案

1. 使用toFixed()方法

(0.1 + 0.2).toFixed(2); // "0.30"

2. 乘以10的n次方后计算

(0.1 * 10 + 0.2 * 10) / 10; // 0.3

3. 使用第三方库

如decimal.js、big.js等专门处理高精度数学运算的库。

五、实际开发中的建议

  1. 金融计算等对精度要求高的场景,避免直接使用浮点数
  2. 比较浮点数时,设置一个误差范围(epsilon)
function floatEqual(a, b) {
    return Math.abs(a - b) < Number.EPSILON;
}
  1. 尽量使用整数进行计算,最后再转换为小数

结语

理解IEEE 754浮点数表示法是每个JavaScript开发者的必修课。虽然0.1 + 0.2 ≠ 0.3看起来很奇怪,但这是计算机科学中的正常现象。在实际开发中,我们需要根据场景选择合适的解决方案来处理浮点数精度问题。