我在开发过程中遇到了这样一个问题:letn1=0.1,n2=0.2console.log(n1+n2)//0.30000000000000004这里得到的不是我想要的如果你想让结果等于0.3,你需要转换它:(n1+n2).toFixed(2)//注意toFixed是四舍五入的。toFixed(num)方法可以将Number舍入为具有指定小数位数的数字。那么为什么会出现这样的结果呢?计算机是以二进制存储数据的,所以计算机在计算0.1+0.2时,实际上是计算两个数的二进制和。0.1的二进制是0.0001100110011001100...(1100周期),0.2的二进制是:0.00110011001100...(1100周期),这两个数的二进制是无限循环的。那么JavaScript如何处理二进制小数的无限循环呢?一般我们认为数字包括整数和小数,但JavaScript中只有一种数字:Number。它的实现遵循IEEE754标准,用64位定长表示,是标准的double双精度浮点数。在二进制科学计数法中,双精度浮点数的小数部分最多只能保留52位,再加上前面的1,实际上保留了53位有效位,其余需要四舍五入,遵循“原则上0舍入1"。根据这个原理,将0.1和0.2的二进制数相加,然后转换成十进制数:0.30000000000000004。我们来看看双精度数是如何存储的:第一部分(蓝色):用于存储符号位(sign),用于区分正负数,0表示正数,占用1位第二部分部分(绿色):用于存放指数(exponent),占用11位。第三部分(红色):用于存放分数(fraction),占用52位。For0.1,itsbinaryvalueis:0.0001100110011001100110011001100110011001100110011001100110011...toscientificnotation(scientificnotationTheresultisthenumberoffloatingpoints):1.1001100110011001100110011001100110011001100110011001*2^-4canseethatthesymbolof0.1is0,theindexbitis-4,十进制位为:100110011001100110011001100110011001。IEEE标准规定了一个偏移量。对于指数部分,每次都加上这个偏移量进行存储,这样即使指数为负数,加上这个偏移量也是正数。由于JavaScript数字是双精度数字,这里我们以双精度数字为例。其指数部分为11位,可表示的范围为0~2047。IEEE固定双精度数的偏移量为1023,当指数不全为0或不全为1(归一化值)时,IEEE规定指数的计算公式为e-Bias。此时e的最小值为1,则1-1023=-1022,e的最大值为2046,则2046-1023=1023。可以看出本例中取值范围为-1022~1013。当指数位全部为0(非归一化值)时,IEEE规定指数编码的计算公式为1-Bias,即1-1023=-1022。当所有的指数位都为1(特殊值)时,IEEE规定这个浮点数可以用来表示3个特殊值,即正无穷大、负无穷大和NaN。具体来说,当小数位不为0时,表示NaN;当小数位为0时,符号位s=0时表示正无穷大,当s=1时表示负无穷大。对于上面0.1的指数是-4,-4+1023=1019换算成二进制是:1111111011。所以0.1表示为:01111111011100110011001100110011001100110011001100110011100111001100110011001110011001=0.01开始的时间说了这么多,0.0是什么意思0.3?解决此问题的一个直接方法是设置误差范围,通常称为“机器精度”。对于JavaScript,这个值通常是2-52。在ES6中,提供了Number.EPSILON属性,其值为2-52。判断0.1+0.2-0.3是否小于Number.EPSILON即可。如果小于,则可以判断为0.1+0.2===0.3functionnumberepsilon(arg1,arg2){returnMath.abs(arg1-arg2)
