http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
如果您创建自定义算法 确定是否有两个浮点 你可以认为数字是平等的 必须使用大于的值 Epsilon不断建立起来 可接受的绝对边际 这两个值的差异 被认为是平等(通常,那 差异很大一倍 大于Epsilon。)
这不是真的可以用于比较的epsilon吗?我真的不明白MSDN的措辞。
这里的例子中可以用作epsilon吗? - What is the most effective way for float and double comparison?
最后这看起来非常重要,所以我想确保我有一个可靠的实现平等,大于,小于,小于或等于,大于或等于。
答案 0 :(得分:74)
我不知道他们写的时候吸烟了什么。 Double.Epsilon
是最小的可表示非非正规浮点值,不是0.你所知道的是,如果存在截断错误,它将始终大于。更大。
System.Double
类型可以表示最多15位数的值。因此,如果双值x
等于某个常数,则简单的一阶估计是使用常数* 1E-15的epsilon
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
都是计算值,则必须增加epsilon。
答案 1 :(得分:45)
我想确保我有一个可靠的实现,包括大于,小于,小于或等于,大于或等于。
您正在使用二进制浮点运算。
二进制浮点运算用于表示物理量,如长度,质量,电荷,时间等。
据推测,您正在使用二进制浮点运算,因为它是用于对物理量进行算术运算。
物理量的测量始终具有特定的精度,具体取决于用于测量它们的设备的精度。
由于您是为您操纵的数量提供值的人,因此您就知道该数量上的“误差条”是什么。例如,如果您提供的数量“建筑物的高度为123.56米”,那么您知道这精确到厘米,而不是微米。
因此,当比较两个相等的数量时,所需的语义是“这两个数量是否在每个测量指定的误差条内相等?”
现在我们已经回答了你的问题。你必须做的是跟踪每个数量的错误;例如,建筑物的高度“在123.56米的0.01之内”,因为您知道测量的精确度。如果您再获得另一个测量值123.5587并想知道两个测量值是否在误差容差范围内“相等”,则进行减法并查看它是否属于误差容限。在这种情况下确实如此。如果测量结果实际上对于微米是精确的,则它们不相等。
简而言之:你是这里唯一知道什么是明智的错误容忍度的人,因为你是唯一一个知道你操纵的数字来自哪里的人。根据您用于生产设备的精度,使用对测量有意义的任何误差容差。
答案 2 :(得分:9)
如果你有两个接近1.0的双精度值,但它们的最低有效位不同,那么它们之间的差异将比Double.Epsilon大许多个数量级。实际上,差异是324个十进制数量级。这是因为指数部分的影响。 Double.Epsilon上有一个巨大的负指数,而1.0的指数为零(当然,除去偏差之后)。
如果要比较两个相似的值是否相等,则需要选择适合要比较的值的数量级大小的自定义epsilon值。
如果您要比较的双精度值接近1.0。那么最小重要位的值将接近0.0000000000000001。如果您要比较的双精度值在四元组中,那么最低有效位的值可能高达一千。在这两种情况下,epsilon的单个值都不能用于相等比较。
答案 3 :(得分:6)
我刚刚这样做 - 使用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;
}
答案 4 :(得分:4)
它可以用于比较,假设您要确保两个值完全相等,或者具有double类型的最小可表示差异。一般来说,您希望使用大于double.Epsilon
的数字来检查两个双打是否大致相等。
为什么.NET框架没有定义类似
的内容bool IsApproximatelyEqual(double value, double permittedVariance);
超出我的范围。
答案 5 :(得分:3)
我认为您发布的MSDN链接中的相关位是:
但是,Epsilon属性不是 一般的精度测量 双重型;它仅适用于Double 值为零的实例。
注意:Epsilon的值 财产不等同于机器 epsilon,代表鞋帮 由于的相对误差的界限 浮点运算中的舍入。
此值未定义为最小值 正数x,这样x + 1.0 不等于1.0,所以Double.Epsilon 不能用于“几乎平等”。 在这里没有任何常数 价值最小的框架 正数x,这样x + 1.0 不等于1.0。
我不得不说,这让我感到惊讶。我也认为Double.Epsilon相当于c / c ++中的DBL_EPSILON - 显然不是!
从我能看到的那个链接看起来似乎是在说“你需要自己为比较找出一个合适的价值”,这至少可以说是令人惊讶的。
也许更有知识的人可以澄清:)
答案 6 :(得分:2)
我使用以下
stdWrap
如果你想检查两个双打的平等性,那么&#39;和&#39; b&#39;,您可以使用
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).IsZero();
答案 7 :(得分:1)
比较双打的问题是,当你在两个不同的数学结果之间进行比较时,由于四舍五入的错误,它们没有评估到相同的值,它们会有一些差别......这是大于epsilon,边缘情况除外。使用可靠的epsilon值也很困难。有些人认为两个双精度相等,如果它们之间的差异小于某个百分比值,因为使用静态最小差异epsilon可能意味着当双精度本身为高或低时,你的差异太小或太大。
答案 8 :(得分:0)
以下是Silverlight Control Toolkit中包含两次的一些代码:
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
。你会想要选择自己的epsilon。
答案 9 :(得分:0)
没有选择你必须自己计算或定义自己的常量。
double calculateMachineEpsilon() {
double result = 1.0;
double one = 1.0/256;
while(one + result/2.0 != 1.0) {
result/=2.0;
}
return result;
}