Double.Epsilon for equal,大于,小于,小于或等于,大于或等于
http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
如果创build一个自定义algorithm来确定两个浮点数是否相等,则必须使用大于Epsilon常数的值来确定两个值的可接受绝对差值,以使其相等。 (通常情况下,差异的边际比Epsilon大很多倍)。
那么这不是一个可以用于比较的小数? 我不太了解MSDN的措辞。
它可以用作例子中的epsilon吗? – 什么是最有效的浮动和双重比较方式?
最后,这似乎非常重要,所以我想确保我有一个坚实的实施平等,大于,小于,小于或等于,大于或等于。
我不知道他们在写什么时吸烟。 Double.Epsilon
是最小的可表示的非Double.Epsilon
浮点值,它不是0.您所知道的是,如果存在截断错误,它将始终大于此值。 更大。
System.Double
types可以表示精确到15位数的值。 所以一个简单的一阶估计,如果一个double值x
等于某个常数,就是使用一个常数ε1E-15
public static bool AboutEqual(double x, double y) { double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15; return Math.Abs(x - y) <= epsilon; }
你必须小心,截断错误可以积累。 如果x
和y
都是计算值,则必须增加ε。
我想确保我有一个坚实的实施平等,大于,小于,小于或等于,大于或等于。
您正在使用二进制浮点运算。
devise二进制浮点运算来表示物理量,如长度,质量,电荷,时间等。
假设你正在使用二进制浮点运算,因为它被用来做:对物理量进行算术运算。
物理量的测量总是具有特定的精度,取决于用于测量它们的设备的精度。
既然你是提供你所操纵的数量值的人,你就知道这个数量上的“误差线”是什么。 例如,如果你提供的数量是“build筑物的高度是123.56米”,那么你知道这是厘米,但不是微米。
因此,在比较两个相等的量时,所需的语义是说:“这两个量在每个测量所指定的误差线内是否相等?
所以现在我们有一个答案你的问题。 你必须做的是跟踪每个数量的错误是什么; 例如,build筑物的高度“在123.56米的0.01以内”,因为你知道测量是多么精确。 如果你再得到另一个123.5587的测量值,并想知道两个测量值是否在容差范围内是“相等的”,那么进行相减,看看它是否落入误差容限内。 在这种情况下呢。 如果这些测量结果实际上是微米级的,那么它们是不相等的。
简而言之:在这里,你是唯一知道什么是合理的容错的人,因为你是唯一知道你操纵的数字来自哪里的人。 考虑到您用来生产设备的精度,请使用任何错误容差对您的测量都有意义。
如果你有两个接近于1.0的double值,但是它们只有最低有效位不同,那么它们之间的差异将比Double.Epsilon大很多数量级。 实际上,差值是324个十进制数量级。 这是因为指数部分的影响。 Double.Epsilon有一个巨大的负指数,而1.0有一个指数为零(当然偏移被去除后)。
如果要比较两个相似的值,则需要select一个适合要比较的值的数量级的大小的自定义epsilon值。
如果你比较的double值接近1.0。 那么最不重要的位的值将接近0.0000000000000001。 如果你正在比较的double值是四倍数,那么最低有效位的值可能高达一千。 在这两种情况下,没有一个单一的价值可以用于平等比较。
我只是做了这个 – 用Kent Bogarts的想法。
private bool IsApproximatelyEqual(double x, double y, double acceptableVariance) { double variance = x > y ? x - y : y - x; return variance < acceptableVariance; //or //return Math.Abs(x - y) < acceptableVariance; }
它可以用于比较,假设您要确保两个值完全相等,或者对于doubletypes具有最小的可表示差异。 一般来说,你会想要使用大于double.Epsilon
的数字来检查两个双打是否大致相等。
为什么.NET框架没有定义类似的东西
bool IsApproximatelyEqual(double value, double permittedVariance);
超越了我。
我认为您发布的MSDN链接中的相关位是这些:
但是,Epsilon属性并不是Doubletypes精度的一般度量; 它仅适用于值为零的Double实例。
注意:Epsilon属性的值不等于机器ε,它代表由于浮点运算中的舍入而导致的相对误差的上限。
这个值没有被定义为最小的正数x,所以x + 1.0不等于1.0,所以Double.Epsilon不能用于“几乎相等”。 在框架中不存在常数,其值是最小的正数x,使得x + 1.0不等于1.0。
我不得不说,这让我感到惊讶。 我也曾假设Double.Epsilon在c / c ++中相当于DBL_EPSILON – 显然不是!
从我所能读到的那个环节来看,似乎是在说“你需要自己去比较一下体面的价值”,这至less是令人惊讶的。
也许有人更knowledgable可以澄清:)
比较双打的问题是,当你比较两个不同的math结果是相等的,但由于舍入误差,没有评估到相同的价值,他们将有一些差异…这是比epsilon ,边缘情况除外。 而使用可靠的epsilon价值也是困难的。 有些人认为两个双打如果他们之间的差异小于某个百分比值相等,因为使用静态最小差异ε可能意味着当双倍本身高或低时,你的差异太小或太大。
以下是在Silverlight控件工具包中包含两次的代码:
public static bool AreClose(double value1, double value2) { //in case they are Infinities (then epsilon check does not work) if(value1 == value2) return true; // This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON; double delta = value1 - value2; return(-eps < delta) && (eps > delta); }
在一个地方,他们使用1e-6
为epsilon; 在另一个他们使用1.192093E-07
。 你会想要select你自己的epsilon。
没有select你必须自己计算或定义自己的常量。
double calculateMachineEpsilon() { double result = 1.0; double one = 1.0/256; while(one + result/2.0 != 1.0) { result/=2.0; } return result; }
我使用以下
public static class MathUtil { /// <summary> /// smallest such that 1.0+EpsilonF != 1.0 /// </summary> public const float EpsilonF = 1.192092896e-07F; /// <summary> /// smallest such that 1.0+EpsilonD != 1.0 /// </summary> public const double EpsilonD = 2.2204460492503131e-016; [MethodImpl( MethodImplOptions.AggressiveInlining )] public static bool IsZero( this double value ) { return value < EpsilonD && value > -EpsilonD; } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static int Sign( this double value ) { if ( value < -EpsilonD ) { return -1; } if ( value > EpsilonD ) return 1; return 0; }
如果你想检查两个双打'a'和'b'的平等,你可以使用
(ab).IsZero();
如果你想得到比较结果,使用
(ab).Sign();