在JavaScript中测试“double”相等性

3
我已经将实验性的C#“float”版本Clipper库翻译成了javascript。在最新的沙盒版本中,有一个IsAlmostEqual函数似乎很难翻译。由于数值稳定性问题,双等号无法使用==运算符进行比较,因此需要这个函数来处理这些问题。 -9223372036854775808 - aInt-9223372036854775808 - bInt可以使用BigInteger库轻松计算,但BitConverter.DoubleToInt64Bits则更难。
有什么想法可以将IsAlmostEqual函数翻译成javascript吗?或者具体如何在javascript中实现BitConverter.DoubleToInt64Bits
private static bool IsAlmostEqual(double A, double B)
{
  //http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

  Int64 aInt = BitConverter.DoubleToInt64Bits(A);
  if (aInt < 0) aInt = unchecked(-9223372036854775808 - aInt);
  Int64 bInt = BitConverter.DoubleToInt64Bits(B);
  if (bInt < 0) bInt = unchecked(-9223372036854775808 - bInt);
  return (Math.Abs(aInt - bInt) <= 10000000000);
}

Numerical stability and robustness: 数值稳定性和健壮性:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
http://www.mpi-inf.mpg.de/~kettner/pub/nonrobust_cgta_06.pdf
http://cpc.cs.qub.ac.uk/MRSN/higham.pdf
http://www.2ality.com/2012/04/number-encoding.html

1个回答

2
我最终使用了完全不同的函数来测试双精度相等性,这个函数可以从这里获得。原始函数使用了双精度的有符号int64表示法,但在Javascript中没有办法做到这一点,除非使用缓慢而复杂的位运算或使用某些BigDecimal库。它结合了相对误差和绝对误差。
根据我的测试结果,它似乎很可靠。请在jsbin中进行测试。
注:我更新了上面的代码。现在,在所有83个测试用例(使用maxUpls 10,000)中,它产生了与ULP技术相同的结果。由于Javascript缺乏64位整数,ULP技术比上述EPSILON技术慢8倍到20倍。

在http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm中提到:“备用maxAbsoluteError的典型值非常小-取决于平台是否支持子规范,通常为FLT_MAX或更小。”我认为应该是FLT_MIN而不是FLT_MAX。我认为Javascript不支持子规范,所以我的答案是否定的。 - Timo Kähkönen
请忽略我之前的评论。FLT_MIN 的值为 5e-324。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_VALUE 上说,小于此值的数会被转换为 0。我无法再做出肯定或否定的回答了。而且我也不确定 Number.MIN_VALUE 是否是 maxAbsoluteError 的正确值。 - Timo Kähkönen
Number.EPSILON似乎是2.220446049250313e-16,因此更合乎逻辑。为什么负指数会使它不合适? - Timo Kähkönen
当我使用Number.EPSILON而不是Number.MIN_VALUE,并比较0和Number.EPSILON/10时,它错误地报告为false。但如果我比较1和1+Number.EPSILON/10,则正确地报告为true。因此,Number.EPSILON似乎不太适合。有什么想法吗? - Timo Kähkönen
Math.abs(0 - Number.EPSILON / 10) < Number.EPSILON 是非常正确的... 我不确定你怎么会得到 false - Ry-
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接