在javascript中测试“双重”平等
我已经将Clipper库的实验性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
我最终使用完全不同的函数来测试双重相等。 原始函数使用双重的有符号int64表示,这在Javascript中是不可能的,不使用慢速和复杂的按位运算或使用某些BigDecimal库。 它使用相对误差和绝对误差的组合。
var IsAlmostEqual = function(a,b) { if(a == b)返回true; var diff = Math.abs(a - b); if(diff <4.94065645841247E-320)返回true; a = Math.abs(a); b = Math.abs(b); var smallest =(b根据我的测试,它似乎可靠。 请在jsbin中测试。
编辑:我更新了上面的代码。 现在它在所有83个测试用例中使用ULP技术产生相同的结果(使用maxUpls 10,000)。 由于Javascript缺少64位整数,ULP技术比EPSILON技术慢8x-20x。