Math.round(num) vs num.toFixed(0) and browser inconsistencies
考虑以下代码:
1 2 3 4 5 | for (var i=0;i<3;i++){ var num = i + 0.50; var output = num +"" + Math.round(num) +"" + num.toFixed(0); alert(output); } |
在Opera 9.63中,我得到:
0.5 1 0
1.5 2 2
2.5 3 2
在FF 3.03中,我得到:
0.5 1 1
1.5 2 2
2.5 3 3
在IE 7中,我得到:
0.5 1 0
1.5 2 2
2.5 3 3
注意粗体结果。 为什么会出现这种不一致? 这是否意味着应避免使用
编辑:要回答您的编辑,请使用
1 2 3 4 5 | Number.prototype.round = function() { return Math.round(this); } var num = 3.5; alert(num.round()) |
我以前从未使用过
我认为FF用toFixed做正确的事情,因为下面的步骤10表示"如果有两个这样的n,则选择较大的n"。
正如Grant Wagner所说:使用Math.ceil(x)或Math.floor(x)代替x.toFixed()。
以下所有内容均来自ECMAScript语言规范:
15.7.4.5
Number.prototype.toFixed (fractionDigits) Return a string containing the number represented in fixed-point
notation withfractionDigits digits after the decimal point. If
fractionDigits is undefined,0 is assumed. Specifically, perform the
following steps:Let f beToInteger(fractionDigits) . (IffractionDigits is undefined,
this step produces the value0 ).If f < 0 orf > 20 , throw aRangeError exception.Let x be this number value.If x isNaN , return the string"NaN" .Let s be the empty string.If x ≥ 0 , go to step 9.Let s be "-" .Let x = –x .If x ≥ 10^21 , letm = ToString(x) and go to step 20.Let n be an integer for which the exact mathematical value of
n ÷ 10^f – x is as close to zero as possible. If there are two
suchn , pick the largern .If n = 0 , letm be the string"0" . Otherwise, letm be the
string consisting of the digits of the decimal representation
ofn (in order, with no leading zeroes).If f = 0 , go to step 20.Let k be the number of characters inm .If k > f , go to step 18.Let z be the string consisting off+1–k occurrences of the
character'0' .Let m be the concatenation of stringsz andm .Let k = f + 1 .Let a be the firstk–f characters ofm , and letb be the
remainingf characters ofm .Let m be the concatenation of the three stringsa ,"." , andb .Return the concatenation of the strings s andm .The
length property of thetoFixed method is1 .If the
toFixed method is called with more than one argument, then the
behaviour is undefined (see section 15).An implementation is permitted to extend the behaviour of
toFixed for
values offractionDigits less than0 or greater than20 . In this case
toFixed would not necessarily throwRangeError for such values.NOTE The output of
toFixed may be more precise thantoString for
some values becausetoString only prints enough significant digits
to distinguish the number from adjacent number values. For example,
(1000000000000000128).toString() returns"1000000000000000100" , while
(1000000000000000128).toFixed(0) returns"1000000000000000128" .
要解决您的两个原始问题/问题:
Math.round(num)与num.toFixed(0)
这里的问题在于误解,认为它们应该总是产生相同的结果。实际上,它们受不同规则的约束。例如看负数。因为
另一方面,根据规范第6步,
浏览器不一致
除IE之外,大多数现代浏览器(或至少在撰写本文时可能期望您支持的浏览器 strike>)都应正确实现规范。 (根据Renee的评论,您在Opera中指出的
结论
简而言之,这是两个不同的函数,具有两个不同的返回类型和两个不同的舍入规则集。
正如其他人所建议的,我也想说"使用适合您特定用例的任何功能"(要特别注意我个人会更倾向于推荐
toFixed()返回一个字符串值。来自Javascript:权威指南
Converts a number to a string that contains a specified number of
digits after the decimal place.
Math.round()返回一个整数。
显然,toFixed()似乎更多地用于金钱,例如,
'$' + 12.34253.toFixed(2) = '$12.34'
似乎很遗憾toFixed()似乎无法正确舍入!
根据要求,使用
如果您得到不一致的答案,肯定可以这样。
我只能猜测,您对toFixed(0)的使用意图是将十进制数转换为整数,这时我建议使用Math.floor()。关于此问题的最佳方法还有更多讨论。