我正在尝试制作一个自适应的“大约相等”方法(用 C# 编写,但问题是一般性的)接受两个 double 并返回一个 bool 值(如果它们是否“大约相等”)。自适应是指:
1.234 和 1.235 ==> 正确
但是
1.234567 和 1.234599 ==> 错误
也就是说,'about equal'的精度适应了数字的精度。
我在 How do I find if two variables are approximately equals? 找到了舍入的概念,但对于 epsilon 使用什么仍然是一个开放式的问题。
有人知道解决此类问题的最佳做法吗? 提前致谢!
编辑: 我最初的问题没有包含足够的信息来说明我想要得到什么。对此感到抱歉,我深表歉意。我想要一个程序,可以将更高的精度数处理为更高的标准,同时对更低的精度数更宽松。对的更多示例是(其中“(0)”是隐含的零):
1.077 和 1.07(0) 返回 false(因为 77 与 70 有很大不同)
1.000077 和 1.00007(0) 返回 false(因为 77 与 70 有很大不同)
1.071 和 1.07(0) 返回 true(因为 71 接近 70
1.000071 和 1.00007(0) 返回真(因为 71 接近 70)
无论实现代码如何,我假设都会有某种“容差”变量来确定什么是“非常不同”和什么是“接近”。
最佳答案
比较 float 的一种方法是比较将它们分开的浮点表示的数量。此解决方案对数字的大小无关紧要,因此您不必担心“epsilon”。
可以找到算法的描述 here (最后是 AlmostEqual2sComplement 函数)这是我的 C# 版本。
public static class DoubleComparerExtensions
{
public static bool AlmostEquals(this double left, double right, long representationTolerance)
{
long leftAsBits = left.ToBits2Complement();
long rightAsBits = right.ToBits2Complement();
long floatingPointRepresentationsDiff = Math.Abs(leftAsBits - rightAsBits);
return (floatingPointRepresentationsDiff <= representationTolerance);
}
private static unsafe long ToBits2Complement(this double value)
{
double* valueAsDoublePtr = &value;
long* valueAsLongPtr = (long*)valueAsDoublePtr;
long valueAsLong = *valueAsLongPtr;
return valueAsLong < 0
? (long)(0x8000000000000000 - (ulong)valueAsLong)
: valueAsLong;
}
}
如果你想比较 float ,把所有的double
改成float
,把所有的long
改成int
和 0x8000000000000000
到 0x80000000
。
关于c# - 将 double 与自适应近似相等进行比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10419771/