有点轻阅读后, 这篇文章引起了我的兴趣:
我还以为那是,这两个语句是等价的,因为MSDN的说法:
代表最小正Double值是大于零。 此字段为常数。
好奇,想看看别人怎么想。
编辑:找到一台计算机与VS上运行这个测试。 原来,是的,正如所料,他们是等价的。
[Test]
public void EpsilonTest()
{
Compare(0d);
Compare(double.Epsilon);
Compare(double.Epsilon * 0.5);
Compare(double.NaN);
Compare(double.PositiveInfinity);
Compare(double.NegativeInfinity);
Compare(double.MaxValue);
Compare(double.MinValue);
}
public void Compare(double x)
{
Assert.AreEqual(Math.Abs(x) == 0d, Math.Abs(x) < double.Epsilon);
}
IL代码似乎蒙上这方面的一些光。
小量是简单地与小数部分为1双号,符号0,0指数零与小数部分为0双号,符号0,指数0。
据http://en.wikipedia.org/wiki/IEEE_754-1985 ,用相同的符号和指数浮点数被序数型标尺相比,这意味着(X <1)是相同的为(x == 0)。
现在,是有可能得到一个零,是不是分数= 0,指数= 0(我们不关心的迹象,有一个Math.Abs到位)?
是的,据我可以告诉他们应该是等价的。 这是因为没有什么区别能有比少小量的幅度也非零。
我只在相关的价值,如double.NaN思想,我测试了一下,并PositiveInfinity时等,结果是一样的。 顺便说一句,double.NaN比较了一些返回false。
我不知道你所说的“等价”的意思是在这里,因为这是一个相当模糊的术语。
如果你的意思是,将.NET考虑任何值小于double.Epsilon
等于 0d
,那么是的,正如你的文章链接到清楚地表明。 你可以很容易地证明这一点:
var d1 = 0d;
var d2 = double.Epsilon * 0.5;
Console.WriteLine("{0:r} = {1:r}: {2}", d1, d2, d1.Equals(d2));
// Prints: 0 = 0: True
在这个意义上,如果你以某种方式产生的值x
是小于double.Epislon
,将已经存储在内存中的零值,所以Abs(x)
将只是Abs(0)
这是== 0d
。
但是,这是作为使用.NET保持浮点数的二进制表示的限制:它根本不能比表示非零数小double.Epsilon
所以其四舍五入。
这并不意味着两种说法都“等效”,因为这是完全依赖于上下文的。 显然, 4.94065645841247E-324 * 0.5
不为零,这是2.470328229206235e-324
。 如果你是这样做需要的精度这一水平计算,比不,他们是不等价的 - 而你也运气试图做他们在C#中的。
在大多数情况下,价值double.Epsilon
完全是太小,是任何价值的,也就是说, Abs(x)
应== 0d
的价值远远大于double.Epison
,但C#依赖于你明白这一点; 它会很乐意做计算下来到精度,如果要求。
不幸的是,声明“ Math.Abs(x) < double.Epsilon
相当于Math.Abs(x) == 0d
”是不是真的在所有的ARM系统。
MSDN上Double.Epsilon通过阐明,自相矛盾
上ARM系统中,小量常数的值太小,被检测到,因此它相当于零。
这意味着,在ARM系统中,有小于没有非负双值Double.Epsilon
,所以表达式Math.Abs(x) < double.Epsilon
只是另一种方式说false
。