经验法则测试两个双打在C#中的平等? [英] Rule of thumb to test the equality of two doubles in C#?

查看:119
本文介绍了经验法则测试两个双打在C#中的平等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有一些代码,做一些浮点运算和存储的值双打。因为有些值不能完全以二进制表示的,我怎么测试相等确定性的合理程度?

Let's say I have some code that does some floating point arithmetic and stores the values in doubles. Because some values can't be represented perfectly in binary, how do I test for equality to a reasonable degree of certainty?

我如何确定什么是合理的意思?

How do I determine what "reasonable" means?

能否 double.Epsilon 以某种方式使用吗?

Can double.Epsilon be used in some way?

更新

两件事情。正如@ HO1指出,对于文档 double.Epsilon 指出,当涉及到比较两个双打平等,你可能会想一个价值远大于小量。下面是从文档的相关段落:

Couple things. As @ho1 pointed out, the documentation for double.Epsilon points out that, when it comes to comparing two doubles for equality, you are probably going to want a value much greater than epsilon. Here is the relevant paragraph from the documentation:

两个明显等同浮点数可能不是因为他们至少有显著的数字差异比较平等。例如,C#的表达,(双)1/3 ==(双)0.33333,不会因为在左侧的除法操作具有最大精度,而在右侧的常数是精确仅到指定位数比较相等。如果创建了确定两个浮点数是否可以被认为是平等的自定义算法,您必须使用值是大于小量不断建立差异可接受的绝对余量,要考虑的两个值相等更大。 (通常情况下,差异是利润率的不是小量的高出许多倍。) - 的 http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

Two apparently equivalent floating-point numbers might not compare equal because of differences in their least significant digits. For example, the C# expression, (double)1/3 == (double)0.33333, does not compare equal because the division operation on the left side has maximum precision while the constant on the right side is precise only to the specified digits. If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, you must use a value that is greater than the Epsilon constant to establish the acceptable absolute margin of difference for the two values to be considered equal. (Typically, that margin of difference is many times greater than Epsilon.) -- http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

......但问题是,有多少倍?

...but the question is, how many times greater??

在情况下,它会影响您的回答,我的具体情况涉及几何计算(如点的产品,并使用点和向量交叉产品)。在某些情况下,你的基础上得出不同的结论是否 A ==乙 A>乙 A<乙,所以我在寻找拇指如何确定等价窗口的大小的一个很好的规则。

In case it would affect your answer, my particular situation involves geometry calculations (such as dot products and cross products using points and vectors). In some cases, you reach different conclusions based on whether A == B, A > B, or A < B, so I'm looking for a good rule of thumb for how to determine the size of the equivalence window.

推荐答案

使用 double.Epsilon 不一定工作。 double.Epsilon 给出了最小可表示值大于零。然而,由于浮点数的实现方式,他们有较少的精度进一步远离零它们,所以检查的 double.Epsilon 可能会失败的区别。两个大数是非常接近彼此

Using double.Epsilon does NOT necessarily work. double.Epsilon gives the smallest representable value that is greater than zero. However, because of the way that floating point numbers are implemented, they have less precision the further away from zero they are, so checking for a difference of double.Epsilon could fail for two large numbers that are very close to each other.

详情:一个基-2-浮点数被表示为有效数字 - 1和2之间的数字 - 乘以两次上调一些指数。双先后为尾数的小数部分52位加精度指数11位。如果该指数是一个非常大的负值,尾数为0,那么你亲近 double.Epsilon 价值,但如果你的指数是足够大,那么即使是非常两个有效数值小的差异会导致比 double.Epsilon 更大的值。

Details: A base-2 floating point number is represented as a significand - a number between 1 and 2 - multiplied by two raised to some exponent. A double has 52 bits for the fractional portion of the significand plus 11 bits of precision for the exponent. If the exponent is a very large negative value and the significand is 0, then you get values close to double.Epsilon, but if your exponent is big enough, then even a very small difference in two significands' values will result in a value much larger than double.Epsilon.

有关全如何测试两个浮点数平等讨论,请参阅的由布鲁斯·道森浮点数2012年版,比较。总之,有比较的方式主要有三种:

For a full discussion on how to test two floating point numbers for equality, see "Comparing Floating Point Numbers, 2012 Edition", by Bruce Dawson. To summarize, there are three main methods of comparison:

作为的乔尔Coehoorn的例子,但要非常慎重选择的值是一个适当的幅度,不像乔尔的例子。

As in Joel Coehoorn's example, but be very careful to select a value that's of an appropriate magnitude, unlike Joel's example.

类似以下内容:

if (Math.Abs(a - b) / b <= maxRelativeError)
{
    return true;
}



不过,也有并发症;您应该由两个值的大分裂,而这个函数的不良接近零值执行,除非您还添加了支票的最大差值的绝对值。详情请参阅文件。

However, there are complications; you should divide by the larger of the two values, and this function performs poorly for values close to zero unless you also add a check for a maximum absolute difference. See the paper for details.

比较使用最后一个地方的单位(ULPS)意味着检查尾数的最后一部分。 (本文称此为使用整数比较。)这是一个比较复杂的方法,但很稳健。本文提供了在C源代码;对于C#,你很可能使用 BitConverter.DoubleToInt64Bits

Comparison using units of last place (ULPs) means checking the last portion of the significand. (The paper refers to this as "Comparing using integers.") This is a more complicated approach but is very robust. The paper provides source code in C; for C#, you could probably use BitConverter.DoubleToInt64Bits.

多少倍?这确实是你的应用领域,这可能是为什么在.NET Framework不提供默认方法的问题,但我一直在使用为4的最大ULPS差异比较ULPS有好运气。

"How many times greater?" This is really a question of your application domain, which is probably why the .NET Framework doesn't provide a default method, but I've had good luck using the ULPs comparison with a max ULPs difference of 4.

这篇关于经验法则测试两个双打在C#中的平等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆