Javascript 浮点数精度问题

为什么0.1+0.2=0.30000000000000004?

因为在计算机内部使用二进制储存浮点数(IEEE 754),其不能准确地表示0.1,0.2或0.3
当编码解释代码时,你的“0.1”已经舍入为该格式的最接近的数字,即使在计算发生之前也会导致小的舍入误差。

1
2
3
4
5
6
十进制0.1 = 0.00011001100110011...(循环0011)
十进制0.2 = 0.0011001100110011...(循环0011)
两者相加:
0.00011001100110011001100110011001100110011001100110011001 + 0.00110011001100110011001100110011001100110011001100110011 = 0.01001100110011001100110011001100110011001100110011001100
转换成10进制之后得到:0.30000000000000004!

为什么电脑使用这样一个愚蠢的系统?

这不是愚蠢的,只是不一样。十进制数字不能准确地表示像1/3的数字,所以你只能得到像0.33这样的一个数字,你不会指望0.33 + 0.33 + 0.33加起来等于1是吧?

计算机使用二进制数,因为它们在处理这些数据时速度更方便。(二进制有什么好处,为何电脑都采用二进制?

如何处理金额运算等对精度要求高的场景?

在别的一些语言中,比如 c#,Java,提供了单精度和双精度的数据类型,来应对不同的精度要求

Javascript 是一门弱类型语言,所有的数字都是 Number 类型,而且 Number 和 String 之间可以隐式转换,当我们需要强制转换成浮点数的话,可以使用parseFloat()函数。

1
var num = parseFloat("3.5");

bignumber.js

一个专门处理十进制小数运算的库

1
2
3
4
0.3 - 0.1 // 0.19999999999999998
x = new BigNumber(0.3)
x.minus(0.1) // "0.2"
x // "0.3"