当前位置:  开发笔记 > 编程语言 > 正文

Math.round(num)vs num.toFixed(0)和浏览器不一致

如何解决《Math.round(num)vsnum.toFixed(0)和浏览器不一致》经验,为你挑选了4个好方法。

请考虑以下代码:

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

注意粗体结果.为什么会出现这种不一致的情况?这是否意味着toFixed(0)应该避免?将数字舍入到最接近的整数的正确方法是什么?



1> tj111..:

编辑:要回答您的编辑,请使用Math.round.Number如果您更喜欢这种语法,您还可以对对象进行原型设计以使其进行出价.

Number.prototype.round = function() {
  return Math.round(this);
}
var num = 3.5;
alert(num.round())

我从来没有使用Number.toFixed()之前(主要是因为大多数JS库提供了一个toInt()方法),但你的结果来看,我会说这将是更一致的使用Math方法(round,floor,ceil),那么toFixed如果跨浏览器的一致性是你在找什么.


同样重要的是要提到Math.round非常快:`Math.round()`比`.toFixed`(https://jsperf.com/math-round-vs-tofixed2)快近500%.
是不是[不良做法](https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/)修改原生对象(即`Number`)?

2> some..:

我认为FF正在使用toFixed做正确的事情,因为下面的第10步说"如果有两个这样的n,请选择更大的n."

正如Grant Wagner所说:使用Math.ceil(x)Math.floor(x)代替x.toFixed().

以下所有内容均来自ECMAScript语言规范:

15.7.4.5 Number.prototype.toFixed (fractionDigits)

返回一个字符串,其中包含以定点表示法表示的fractionDigits数字和小数点后的数字.如果 fractionDigits未定义,0则假设.具体而言,执行以下步骤:

    我们fToInteger(fractionDigits).(如果fractionDigits未定义,则此步骤生成值0).

    如果f < 0f > 20,抛出RangeError异常.

    x这个数值.

    如果xNaN,则返回字符串"NaN".

    让我们s成为空字符串.

    如果x ? 0,请转到步骤9.

    我们是"-".

    我们x = –x.

    如果x ? 10^21,让我们m = ToString(x)去第20步.

    n是一个整数,其确切的数学值 n ÷ 10^f – x是接近零越好.如果有两个这样n,选择较大的n.

    如果n = 0,让我们m成为字符串"0".否则,m设为由十进制表示的数字组成的字符串n(按顺序,没有前导零).

    如果f = 0,请转到步骤20.

    让我们k在字符数m.

    如果k > f,请转到步骤18.

    我们z是由字符串f+1–k的字符的出现'0'.

    我们m是字符串的串联zm.

    我们k = f + 1.

    让我们a成为第一个k–f角色m,让b剩下的f角色成为m.

    m是三个字符串的串联a,"."b.

    返回字符串的连接sm.

该方法的length属性toFixed1.

如果toFixed使用多个参数调用该方法,则行为未定义(请参阅第15节).

允许实现扩展小于或大于的toFixed值的行为.在这种情况下 ,不一定会抛出这样的值.fractionDigits020toFixedRangeError

注意输出toFixed可能比toString某些值更精确,因为toString只打印足够的有效数字以区分数字和相邻数字值.例如, (1000000000000000128).toString()返回"1000000000000000100"(1000000000000000128).toFixed(0)返回"1000000000000000128".



3> Noyo..:

解决您的两个原始问题:

Math.round(num)vs num.toFixed(0)

这里的问题在于误解这些应该总是给出相同的结果.事实上,它们受不同规则的约束.例如,查看负数.由于Math.round采用"圆的一半了"作为规则,你会看到,Math.round(-1.5)计算结果为-1,即使Math.round(1.5)计算结果为2.

Number.prototype.toFixed另一方面,根据规范的第6步,使用基本上相当于"从零开始的一半"的规则,基本上将负数视为正数,然后在负数上添加负数.结束.因此,并且是所有符合规范的浏览器中的真实陈述.请注意,这些值是字符串,而不是数字.进一步,无论注意和是(数量),由于运算符优先级.(-1.5).toFixed(0) === "-2"(1.5).toFixed(0) === "2"-1.5.toFixed(0)-(1.5).toFixed(0)=== -2

浏览器不一致

大多数现代浏览器 - 或者至少是你在撰写本文时可能会支持的 浏览器除了IE之外 -都应该正确实现规范.(根据Renee的评论,toFixed你在Opera中指出的问题已得到解决,大概是因为他们开始使用与Chrome相同的JS引擎.)仍然值得重申的是,即使规范在所有浏览器中一致地实现,行为定义也是如此在规范中,特别是对于toFixed舍入,对于那些期望真正的数学准确性的"凡人"JS开发人员来说仍然有点不直观 - 请参阅Javascript toFixed Not Rounding并且这个"按预期工作"的错误已经在V8 JS引擎上提交了示例.

结论

简而言之,这是两个不同的函数,具有两种不同的返回类型和两组不同的舍入规则.

正如其他人所建议的那样,我还想说"使用适合您特定用例的任何函数"(特别注意注意特殊性toFixed,尤其是IE的错误实现).我个人更倾向于推荐一些明确的组合Math.round/ceil/floor,再次,正如其他人所提到的那样. 编辑: ...但是,在回过头来阅读你的澄清之后,你的用例(四舍五入到一个整数)肯定需要一个恰当命名的Math.round函数.



4> Matt..:

toFixed()返回一个字符串值.来自Javascript:The Definitive Guide

将数字转换为包含小数位后指定位数的字符串.

Math.round()返回一个整数.

显然,toFixed()似乎更多用于赚钱,例如,

'$'+ 12.34253.toFixed(2)='$ 12.34'

很遗憾toFixed()似乎没有正确圆!

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有