我已经翻译了 Clipper library 的实验性 C#“ float ”版本到javascript。在最新的沙箱版本中有一个函数 IsAlmostEqual这似乎很难翻译。由于数值稳定性问题,无法使用 == 运算符比较双重相等性,因此需要此函数来处理这些问题。
-9223372036854775808 - aInt
和 -9223372036854775808 - bInt
很容易使用例如计算BigInteger 库,但 BitConverter.DoubleToInt64Bits
更难。
知道如何将 IsAlmostEqual
函数转换为 javascript 吗?或者具体如何将 BitConverter.DoubleToInt64Bits
实现为 javascript?
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);
}
数值稳定性和鲁棒性:
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
最佳答案
我最终使用完全不同的函数来测试来自 here 的双重相等性.原始函数使用 double 的带符号 int64 表示,如果不使用缓慢且复杂的按位运算或使用某些 BigDecimal 库,这在 Javascript 中是不可能的。它结合了相对误差和绝对误差。
var IsAlmostEqual = function(a, b) { if (a == b) return true; var diff = Math.abs(a - b); if (diff < 4.94065645841247E-320) return true; a = Math.abs(a); b = Math.abs(b); var smallest = (b < a) ? b : a; return diff < smallest * 1e-12; }
根据我的测试,它似乎是可靠的。请在jsbin测试.
编辑:我更新了上面的代码。现在它产生与 ULP technique 相同的结果在所有 83 个测试用例中(使用 maxUpls 10,000)。由于 Javascript 缺少 64 位整数,ULP 技术比上述 EPSILON 技术慢 8-20 倍。
关于c# - 在 javascript 中测试 "double"是否相等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20935282/