JavaScript|JavaScript 如何解决数字计算的精度问题

我们前端在做计算过程中,特别时小数的计算,都会遇到意想不到的结果,通常我们在价格的计算中遇到很多问题,这是由于 JS 中的 Number 类型是一个浮点类型。
Nubmer 类型 【JavaScript|JavaScript 如何解决数字计算的精度问题】我们先看看 JS 中的 Number 类型。它并不像其它的语言有不同的数字类型,例如:整型、长整型、浮点类型等等,定义不同的数字类型存储的空间也不一样。然而 JS 中的 Number 类型都是浮点类型并且存储空间为 8 数节(byte)(8*8 bit位)。其中Number 类型值的整数最多15位,小数最多17位。
注:1byte=8bit,1kb=1024byte,1mb=1024kb
精度问题 JS 中的 Number 是一个双精度浮点类型,双精度浮点类型在 64 位存储空间中的内容如下:
todo:

1位 11位 52位
符号位 指数位 小数位
0表示正,1表示负 -1022~+1023 任意
由于计算机在计算的过程中,会把十进制数字先转换成二进制,然后做运算,因为浮点类型的小数位的限制而截断了运算完的二进制,这时候再把它转换成了十进制就产生了精度的问题。
举个例子:
0.1 + 0.2 = ?
  • 0.1 转换成二进制:0.000110011001100110....
  • 0.2 转换成二进制:0.001100110011001100....
  • 0.000110011001100110.... + 0.001100110011001100.... = 0.0100110011001100110011001100110011001100110011001100...还很多,如果超过了 52 位就截断了。
  • 然后转换成十进制:0.30000000000000004
如何解决精度问题 简单的四舍五入
通过简单的四舍五入可以解决一些问题。
(0.1 + 0.2).toFixed(1); //0.3

换算成整型计算
当然这种四舍五入的方式明显是经不起考验的。彻底消除运算过程中的精度,需要将所有数字升位转化为整型了再做计算,计算完毕后再将最终结果进行相应的降位处理。
function add(num1, num2) { var p1 = 0; var p2 = 0; if (num1.toString().split('.').length > 1) { p1 = num1.toString().split('.')[1].length; }if (num2.toString().split('.').length > 1) { p2 = num2.toString().split(".")[1].length; }var p = p1 > p2 ? p1 : p2; var n1 = num1 * Math.pow(10, p); var n2 = num2 * Math.pow(10, p); var result = (n1 + n2) / Math.pow(10, p); return result; }add(0.1, 0.2); //0.3

    推荐阅读