当前位置: 首页 > Web前端 > JavaScript

面试热点问题:为什么0.1+0.2!=0.3,怎么取相等?

时间:2023-03-26 23:53:11 JavaScript

前言欢迎来到“前端进阶圈”公众号,一起探索和学习前端技术……前端小菜鸟,分享的文章纯属个人观点,如有不妥,敬请谅解可以讨论欢迎大家评论交流,和同学一起学习~面试热点:为什么0.1+0.2!=0.3,怎么取相等?开发过程中遇到过这样一个问题:letn1=0.1,n2=0.2;控制台日志(n1+n2===0.3);//false->0.1+0.2=0.30000000000000004这里得到的不是你想要的结果,如果你想等于0.3,你需要转换它:(n1+n2).toFixed(2);//注意toFixed是四舍五入的toFixed(num):该方法可以将Number四舍五入为指定小数位数的数字。为什么会出现0.1+0.2!=0.3?计算机是以二进制存储数据的,所以计算机在计算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.300000000000000004。Howaredoubleprecisionnumbersstored?Thefirstpart(blue):usedtostorethesignbit(sign),usedtodistinguishpositiveandnegativenumbers,0meansapositivenumber,occupying1bitThesecondpart(green):usedtostoretheexponent(exponent),occupying11bits三部分(红色):用来存储小数(fraction),占用52位对于0.1,它的二进制为:0.0001100110011001100110011001100110011001100110011001100110011...转为科学计数法(科学计数法的结果就是浮点数):(1.1001100110011001100110011001100110011001100110011001*2)^-4;Itcanbeseenthatthesignbitof0.1is0,theexponentbitis-4,andthedecimalplaceis:1001100110011001100110011001100110011001100110011001;Thentheproblemcomesagain,theexponentisnegative,howtosaveit?TheIEEEstandardstipulatesanoffset.Fortheexponentpart,thisoffsetisaddedeverytimeforstorage,sothateveniftheexponentisnegative,addingthisoffsetisapositivenumber.SinceJavaScriptnumbersaredouble-precisionnumbers,herewetakedouble-precisionnumbersasanexample.Itsexponentpartis11bits,andtherangethatcanberepresentedis0~2047.TheoffsetofIEEEfixeddouble-precisionnumbersis1023.Whentheexponentisnotall0orall1(normalizedvalue),IEEEstipulatesthattheformulaforcalculatingtheexponentise-Bias.Atthistime,theminimumvalueofeis1,then1-1023=-1022,andthemaximumvalueofeis2046,then2046-1023=1023.Itcanbeseenthatthevaluerangeinthiscaseis-1022~1013.Whentheexponentisall0(non-normalizedvalue),IEEEstipulatesthatthecalculationformulaoftheexponentis1-Bias,thatis,1-1023=-1022.Whenallexponentbitsare1(specialvalue),IEEEstipulatesthatthisfloating-pointnumbercanbeusedtorepresent3specialvalues,whicharepositiveinfinity,negativeinfinity,andNaN.Specifically,whenthedecimalplaceisnot0,itmeansNaN;whenthedecimalplaceis0,whenthesignbits=0,itmeanspositiveinfinity,andwhens=1,itmeansnegativeinfinity.对于上面0.1的指数是-4,-4+1023=1019转换成二进制是:1111111011所以,0.1表示为:11111110111001100110011001100110011001100110011001100110011001如何使它们相等?一个直接的解决方案是设置误差范围,通常称为“机器精度”。对于JavaScript,这个值通常是2-52。在ES6中,提供了Number.EPSILON属性,其值为2-52。判断0.1+0.2-0.3是否小于Number.EPSILON即可。如果小于,则可以判断为0.1+0.2===0.3。函数numberepsilon(arg1,arg2){returnMath.abs(arg1-arg2)