Open ljianshu opened 3 years ago
你好,这个怎么解释呢?如果n一样,取较大的那个,但是实际是取较小的那个
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包!参考文章