Firefox和Javascript舍入规则 [英] Firefox and Javascript Rounding Rules
问题描述
在IE,Opera和Chrome中,我可以得到我所期望的四舍五入数字以5结尾:
125 toPrecision(2)=> 130
11.5 toPrecision(2)=> 12
这是我所期望的。
然而,Firefox虽然稍微复杂一些,但却产生了如下的效果:
125 toPrecision(2)=> 120 // wtf !!!
11.5 toPrecision(2)=> 12
经过一番搔头之后,我得出结论,Firefox正在使用四舍五入的规则,如果5之前的数字甚至是数字减少,并且5之前的数字是奇数,则数字递增:
0.5 => 0
1.5 => 2
2.5 => 2
3.5 => 4等。
我使用四舍五入的结果来测试学生解决方案的伪随机工程问题生成问题输入。在Chrome中输入的问题可能是h = 1020毫米,但在FF,Chrome或Opera中h = 1030毫米。
我需要一个使圆整一致的函数, 0.0001235加起来0.000124,我想要1234到1240,所以我不能用简单的num = Math.floor(num + 0.5);让事情复杂一点,我想输入变量和学生的答案是正确的3 sig挖掘,除非第一个数字是1,在这种情况下,我想4 sig挖:
234.5 => 235
134.5 => 134.5
我已经根据第一个数字转换了3或4个信号的解决方案将数字转换为字符串并测试1的第一个非零非小数点和非负数字符 - 不是很漂亮,但它起作用。我可以做类似的四舍五入问题,检查是否要舍入的数字是5,但我想知道是否有一个优雅的按位解决方案。
请看这里的测试
http://yuiblog.com/blog/2009/03/10/when-you-cant-count-
$ b
JavaScript具有单一数字类型:
IEEE 754双精度浮动
点。有一个单一的数字类型是
JavaScript的最好的功能之一。
多个数字类型可能是复杂性,混乱和错误的源
。
单一类型是简化和
稳定。
不幸的是,二进制浮点
类型有一些显着的
缺点。最糟糕的是,它
不能准确地表示十进制
分数,这是一个大问题
,因为人类已经做了
商业小数的长期,长
时间。
切换到基于二进制的数字
系统会有好处,但是这不会发生
。因此,0.1 + 0.2
=== 0.3是错误的,这是很多混乱的根源。
也看看这个SO问题:
和
https://stackoverflow.com/questions/744099/javascript-bigdecimal-library/1575569#1575569
I don't know if I'm missing something obvious here but...
In IE, Opera and Chrome, I get what I expect from rounding numbers ending in a 5:
125 toPrecision(2) => 130
11.5 toPrecision(2) => 12
This is what I'd expect.
Firefox, though, is a little more 'sophisticated' yielding the following:
125 toPrecision(2) => 120 //wtf!!!
11.5 toPrecision(2) => 12
After a bit of head scratching, I've come to the conclusion that Firefox is using a 'rounding even' rule where, if the digit before the 5 is even the number rounds down and if the digit before the 5 is odd the number rounds up:
0.5 => 0
1.5 => 2
2.5 => 2
3.5 => 4, etc.
I am using the rounded results to test student solutions to engineering questions with pseudo-randomly generated question inputs. A question input in Chrome could be h=1020 mm but h=1030 mm in FF, Chrome or Opera.
I need a function to make rounding consistent, i.e. I want 0.0001235 to round up to 0.000124 and I want 1234 to round to 1240 so I can't use a simple num = Math.floor(num + 0.5); To complicate matters a bit, I want input variables and student answers to be correct to 3 sig digs unless the first digit is a 1, in which case I want 4 sig digs:
234.5 => 235
134.5 => 134.5
I've hacked a solution to the 3 or 4 sig digs depending upon the first digit by converting the number to a string and testing the first non-zero, non-decimal point and non-negative character for '1' - not pretty, but it works. I could do something similar for the rounding problem, checking whether the digit to be rounded is a 5 but I'm wondering if there is an elegant bit-wise solution.
Please take a look at the tests here
http://yuiblog.com/blog/2009/03/10/when-you-cant-count-on-your-numbers/
JavaScript has a single number type: IEEE 754 Double Precision floating point. Having a single number type is one of JavaScript’s best features. Multiple number types can be a source of complexity, confusion, and error. A single type is simplifying and stabilizing.
Unfortunately, a binary floating point type has some significant disadvantages. The worst is that it cannot accurately represent decimal fractions, which is a big problem because humanity has been doing commerce in decimals for a long, long time. There would be advantages to switching to a binary-based number system, but that is not going to happen. As a consequence, 0.1 + 0.2 === 0.3 is false, which is the source of a lot of confusion.
Also take a look at the SO questions:
and
https://stackoverflow.com/questions/744099/javascript-bigdecimal-library/1575569#1575569
这篇关于Firefox和Javascript舍入规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!