奇怪的BUG
在保留有效数字的时候我们经常会使用到这个函数。但各个浏览器的实现有所不同:
Edge的实现:
Firefox的实现:
Chrome的实现:
Safari的实现:
如果不仔细对比,就无法看出不同浏览器在toFixed函数实现上存在的差异。
这些差异是如何造成的呢?首先我们得从数值修约说起。在保留近似值的做法上,除了了我们熟悉的四舍五入,还有一种很少被提起的修约方法—-四舍六入五留双。关于“四舍六入五留双”这种规则,在维基百科是这样解释的。
引入“四舍六入五留双”,是为了解决入得多舍得少的问题,在这之间达到平衡。然而各浏览器在toFixed上既没有把四舍五入做好,也没有按“四舍六入五留双”来实现,结果让人捉摸不透。
如何做到真正的四舍五入?
我们知道Math.round可以实现真正的四舍五入,我们可以这么解决:
1 2 3 4 5 6 7 8 9 10 11 |
function decimalAdjust(c, a, b) { if ("undefined" === typeof b || 0 === +b) return Math[c](a); a = +a; b = +b; if (isNaN(a) || "number" !== typeof b || 0 !== b % 1) return NaN; a = a.toString().split("e"); a = Math[c](+(a[0] + "e" + (a[1] ? +a[1] - b : -b))); a = a.toString().split("e"); return +(a[0] + "e" + (a[1] ? +a[1] + b : b)) } Math.round10 || (Math.round10 = function(c, a) {return decimalAdjust("round", c, a) }); |
发散思维:如果要真是实现“四舍六入五留双”,该如何拓展呢?那就留给大家思考了?
附加参考链接:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/round