面试题答案
一键面试原因
在JavaScript中,数字以IEEE 754双精度64位格式存储。0.1和0.2在二进制中是无限循环小数,存储时会进行近似,导致相加后的结果与0.3的二进制表示存在细微差异,所以 0.1 + 0.2
不等于 0.3
。具体来说:
- 0.1的二进制表示为:
0.0001100110011001100110011001100110011001100110011001101
(无限循环,存储时会截断近似) - 0.2的二进制表示为:
0.001100110011001100110011001100110011001100110011001101
(无限循环,存储时会截断近似) - 二者相加后结果的二进制表示与0.3的二进制表示
0.01001100110011001100110011001100110011001100110011001101
存在差异。
解决方法
- 使用
toFixed()
方法: 可以对结果使用toFixed()
方法进行四舍五入,设定保留的小数位数。
let result = (0.1 + 0.2).toFixed(1);
console.log(result === '0.3'); // true
但 toFixed()
返回的是字符串,如果需要数字类型,还需进一步转换。
2. 使用 Math.round()
方法:
先将数字乘以一个10的幂次方,使小数变为整数,进行运算后再除以相同的幂次方,并使用 Math.round()
进行四舍五入。
let num1 = 0.1;
let num2 = 0.2;
let result = Math.round((num1 + num2) * 10) / 10;
console.log(result === 0.3); // true
- 使用
BigInt
(ES2020 引入):BigInt
类型可以表示任意精度的整数。先将小数转换为整数进行运算,再转换回小数。
let num1 = 0.1 * 10n;
let num2 = 0.2 * 10n;
let result = Number((num1 + num2) / 10n);
console.log(result === 0.3); // true
- 使用第三方库如
decimal.js
:decimal.js
提供了用于任意精度算术的Decimal类型。
const Decimal = require('decimal.js');
let num1 = new Decimal(0.1);
let num2 = new Decimal(0.2);
let result = num1.plus(num2).equals(new Decimal(0.3));
console.log(result); // true