toFixed的结果可能会欺骗你

89 阅读1分钟

1.现象

让我们看下几个案例:

1.55.toFixed(1) => 1.6

2.55.toFixed(1) => 2.5

解释:

toFixed()的作用是保留小数位数,多余的位数进行四舍五入;

但是2.55应该四舍五入为2.6,为什么这里是2.5;

根本原因是小数在计算机中存储不一定准确,而计算机存储的位数是有限的; 2.55.toPrecision(20) => '2.5499999999999998224'

正如你所看到的,计算机上实际存储的并不完全是2.55

2.根本原因:存储可能不准确

小数部分是1/(2^n)的,都可以在计算机中精确表示.

0.25.toPrecision(20) => '0.25000000000000000000' 1/(2^2)

0.125.toPrecision(20) => '0.12500000000000000000' 1/(2^3)

0.0625.toPrecision(20) => '0.06250000000000000000' 1/(2^4)

3.次要原因:计算可能不准确

例1:0.2 + 0.3 === 0.5 => true

0.2.toPrecision(20) => '0.20000000000000001110'

0.3.toPrecision(20) => '0.29999999999999998890'

0.2实际存储的值偏大,0.3实际存储的值偏小,一来一去反而精确了。

例2:0.3 - 0.2 === 0.1 => false 0.09999999999999998

0.2实际存储的值偏大,0.3实际存储的值偏小,偏小的减去偏大的,比实际值更小了

4.次要原因:表示可能不准确

JS引擎可能会对一些值使用近似值

const a = 0.2; //=> 实际存储的是 0.20000000000000001110

console.log(0.2); //=> 0.2

0.2 ===0.20000000000000001110 => true

5.解决方案

使用第三方库 或者 存储为字符串,遍历字符串计算(计算效率会降低)

第三方库:decimal.js
www.npmjs.com/package/dec…