-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
慎用Number.toFixed() #95
Comments
Thanks for the information.. https://www.mygeorgiasouthern.org/ |
您好,您的来信已收到,我会尽快阅读且回复,谢谢!
|
When I tried to use IEEE 754 MIPS single precision representation (1-bit sign, 8-bit exponent, 23-bit fraction) to store the floating point decimal into binary and then convert back to decimal, if the last 3 bits of the fraction field are recognized as guard, round, and sticky, the calculated result is 1.334, which would round down to 1.33 like it showed up in your example. I haven't test it so this is just a thought but would creating an algorithm with threshold for deciding which precision representation to use (use a larger precision when needed) to store the decimal be another way to solve this problem? |
引言
最近在公司项目中碰到一个隐藏的bug,调试许久才发现竟然是
toFixed
函数精度问题引起的,从而引发了我一系列的思考。我们都知道,计算机在二进制环境下,浮点数的计算精度会存在缺失问题,最经典的例子就是为什么0.1+0.2不等于0.3?
遇到上述问题,我们自然而然会想到
toFixed
方法来四舍五入,可结果却差强人意!toFixed()的精度问题
我们来看一下
toFixed
在chrome、火狐、IE浏览器下的不同表现:可以看到
toFixed
的四舍五入在chrome、火狐上并不准确。而
toFixed
在chrome、火狐上也并不是网上流传甚广的用银行家舍入法来进行四舍五入的。例如银行家舍入法在 (2.55).toFixed(1) = 2.5、(3.55).toFixed(1) = 3.5 上就不符合了。
翻阅ecmascript规范对
toFixed
的表述如下:上面规范这段大概意思就是如果
toFixed
的入参小于10的21次方,那么就取一个整数n,让n*10^f - x 的精确值尽可能的趋近于0,如果存在两个这样的n,取较大的n。这段话可能有点晦涩难懂,我们举个例子比如 1.335.toFixed(2)上图例子中1.335.toFixed(2)按照四舍六入五成双应该是1.34,但是实际情况确实1.33。这是因为n=133的时候让n*10^f - x更趋近于0,所以最后得到的结果是1.33。
解决方法
1.重写toFixed()
我们可以通过重写
toFixed
的方法,来实现四舍五入:该方法的大致思路是首先找到舍入位,判断该位置是否大于等于5,条件成立手动进一位,然后通过参数大小将原浮点数放大10的参数指数倍,然后再将包括舍入位后的位数利用
Math.floor
全部去掉,根据我们之前的手动进位来确定是否进位。2.high-precision-four-fundamental-rules
在GitHub上找到一个高精度的基本四则运算npm包,用来弥补原生JS中
toFixed
方法计算精度缺失的不足,该作者用四舍五入算法重写了改方法,并封装成npm包!参考文章
The text was updated successfully, but these errors were encountered: