Math.hypot() 在 Chrome 和 Firefox 上的不同结果
Different results of Math.hypot() on Chrome and Firefox
当我运行下面的简单计算结果在Chrome和Firefox上略有不同。
Chrome: 56.1124478168614
火狐: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 计算正确。
虽然Math.js
在两个浏览器中是相同的代码,但不同的引擎有不同的算法来执行基本运算。例如,有许多不同的计算平方根的方法,两个不同的引擎不太可能共享完全相同的实现。
有一些努力使引擎的精度标准化,但它们尚未成功。例如,参见 this article。
至于为什么 Chrome 中的 Math.hypot
会 return 与在同一引擎中手动计算的值不同,Math.hypot
旨在作为一种有效的近似值——而不仅仅是一种简洁的方法将工作打包成一个函数。因此,根据实施情况,其结果可能与实际计算不同。你说得对,在这种情况下,Firefox 的实现在数值上更准确,你的简单测试证明了这一点。
In Firefox Math.hypot(x, y)
gives the same result as Math.sqrt(x*x, y*y)
这让我们可以相当自信地猜测 Firefox 是如何实现的 Math.hypot
:-)
in Chrome the result from Math.hypot(x, y)
is slightly different
这是 Chrome 的实现:
https://chromium.googlesource.com/v8/v8/+/master/src/builtins/math.tq#389
正如您从第 421 行的注释中看到的那样,Kahan 求和用于 avoid/minimize 舍入误差——因此显然意图是 更 准确而不是简单的 sqrt(x*x + y*y)
实现。 (我已经尝试验证这是否真的是这种情况下的结果,但 Wolfram Alpha 只是四舍五入到 56.1124
,而且我不知道那里还有另一个方便的无限精度浮点计算器,所以我可以'肯定地说。)
doing the calculation correctly
在存在有限精度和舍入误差的情况下,很难定义“正确”的方法。例如,有些情况下(数学上等价!)表达式 (a * b) / c
和 a * (b / c)
由于四舍五入而产生不同的结果,而且,a、b、c 的值决定了哪种计算方式结果更接近(无限精度)理论结果,因此每个实现都可能变得“幸运”或“不幸”。
当我运行下面的简单计算结果在Chrome和Firefox上略有不同。
Chrome: 56.1124478168614
火狐: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 计算正确。
虽然Math.js
在两个浏览器中是相同的代码,但不同的引擎有不同的算法来执行基本运算。例如,有许多不同的计算平方根的方法,两个不同的引擎不太可能共享完全相同的实现。
有一些努力使引擎的精度标准化,但它们尚未成功。例如,参见 this article。
至于为什么 Chrome 中的 Math.hypot
会 return 与在同一引擎中手动计算的值不同,Math.hypot
旨在作为一种有效的近似值——而不仅仅是一种简洁的方法将工作打包成一个函数。因此,根据实施情况,其结果可能与实际计算不同。你说得对,在这种情况下,Firefox 的实现在数值上更准确,你的简单测试证明了这一点。
In Firefox
Math.hypot(x, y)
gives the same result asMath.sqrt(x*x, y*y)
这让我们可以相当自信地猜测 Firefox 是如何实现的 Math.hypot
:-)
in Chrome the result from
Math.hypot(x, y)
is slightly different
这是 Chrome 的实现:
https://chromium.googlesource.com/v8/v8/+/master/src/builtins/math.tq#389
正如您从第 421 行的注释中看到的那样,Kahan 求和用于 avoid/minimize 舍入误差——因此显然意图是 更 准确而不是简单的 sqrt(x*x + y*y)
实现。 (我已经尝试验证这是否真的是这种情况下的结果,但 Wolfram Alpha 只是四舍五入到 56.1124
,而且我不知道那里还有另一个方便的无限精度浮点计算器,所以我可以'肯定地说。)
doing the calculation correctly
在存在有限精度和舍入误差的情况下,很难定义“正确”的方法。例如,有些情况下(数学上等价!)表达式 (a * b) / c
和 a * (b / c)
由于四舍五入而产生不同的结果,而且,a、b、c 的值决定了哪种计算方式结果更接近(无限精度)理论结果,因此每个实现都可能变得“幸运”或“不幸”。