例子
在js的小数计算中,0.1+0.2=0.30000000000000004
let num1 = 0.1; let num2 = 0.2; console.log( num1 + num2 ); // 0.30000000000000004
为什么
为什么出现这样的结果,我们把小数转换成计算机能读得懂的二进制就比较明了了
// 0.1 -> 0.1.toString(2) -> 0.0001100110011001100110011001100110011001100110011001101(无限循环…) // 0.2 -> 0.1.toString(2) -> 0.001100110011001100110011001100110011001100110011001101(无限循环…)
双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串
- 0.0100110011001100110011001100110011001100110011001100
因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004
如何处理此类问题?
- 为了避免产生精度差异,我们要把需要计算的数字乘以 10 的 n 次幂,换算成计算机能够精确识别的整数,然后再除以 10 的 n 次幂,大部分编程语言都是这样处理精度差异的,我们就借用过来处理一下 JS 中的浮点数精度误差。
formatNum = function( num, digit ) {
let m = Math.pow( 10, digit );
return parseInt( num * m, 10 ) / m;
}
let num1 = 0.1;
let num2 = 0.2;
console.log( num1 + num2 );
console.log( formatNum( num1 + num2, 1) );
// Tips:
// pow() 方法可返回 x 的 y 次幂的值。
// parseInt() 函数可解析一个字符串,并返回一个整数。(第二个参数取值2-36,省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。)