当我在下面运行简单计算时,Chrome和Firefox上的结果略有不同。
Chrome浏览器:56.1124478168614
Firefox:56.11244781686139
let x = -24.42;
let y = -50.519999999999925;
console.log(Math.hypot(x, y));
Math.hypot()
的规范中是否存在漏洞?或者是其中一种浏览器以错误的方式实现了该错误?
编辑:在Firefox Math.hypot(x, y)
中,结果与Math.sqrt(x*x, y*y)
相同;在Chrome中,Math.hypot(x, y)
中的结果略有不同。因此,我怀疑Firefox在正确地进行计算。
答案 0 :(得分:1)
尽管Math.js
在两个浏览器中都是相同的代码,但是不同的引擎具有不同的算法来执行基本算术。例如,计算平方根的方法有很多,并且两个不同的引擎不太可能共享完全相同的实现。
目前正在努力使各个发动机的精度标准化,但迄今为止还没有成功。例如,请参见this article。
关于为什么Chrome中的Math.hypot
会在同一引擎中手动执行计算时返回不同的值的原因,Math.hypot
旨在作为一种有效的近似值-不仅仅是将工作包装成一个单一的巧妙方法功能。因此,根据实现方式,其结果可能与实际计算有所不同。您正确地说,在这种情况下,通过简单的测试即可证明Firefox具有更精确的数字实现。
答案 1 :(得分:1)
在Firefox中,
Math.hypot(x, y)
与Math.sqrt(x*x, y*y)
的结果相同
这使我们对Firefox如何实现Math.hypot
:-)
在Chrome中,
Math.hypot(x, y)
的结果略有不同
这是Chrome的实现:
https://chromium.googlesource.com/v8/v8/+/master/src/builtins/math.tq#389
从第421行的注释中可以看到,Kahan求和用于避免/最小化舍入误差-因此显然,其目的是比简单的{{1} }实施。 (我已经尝试验证在这种情况下是否真的是结果,但是Wolfram Alpha只是四舍五入为sqrt(x*x + y*y)
,而且我不知道那里还有另一个方便的无穷精度浮点评估器,因此我可以不能肯定地说。)
正确进行计算
在有限的精度和舍入误差的情况下,很难定义“正确”的方式。例如,在某些情况下,(四舍五入!)表达式56.1124
和(a * b) / c
由于舍入而产生不同的结果,而且,a,b,c的值决定了哪种计算方式结果接近(无限精度)理论结果,因此每个实现都可能是“幸运的”或“不幸的”。