经过一番轻松阅读后,this article引起了我的兴趣:
我认为是的,这两个陈述是等价的,给出了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);
}
答案 0 :(得分:4)
IL代码似乎对此有所了解。
Epsilon只是一个双数,分数部分为1,符号0,指数为0。 零是一个双数,小数部分为0,符号0,指数为0。
根据http://en.wikipedia.org/wiki/IEEE_754-1985,具有相同符号和指数的浮点数通常被比较,这意味着(x <1)与(x == 0)相同。
现在,是否有可能得到零不是分数= 0,指数= 0(我们不关心标志,那里有Math.Abs)?
答案 1 :(得分:1)
是的,据我所知,它们应该是等价的。这是因为没有差异的幅度小于epsilon,也不是非零。
我唯一的想法是关于double.NaN等值,我测试了它和PositiveInfinity等,结果是一样的。顺便说一下,将double.NaN与数字进行比较会返回false。
答案 2 :(得分:1)
我不确定你的“等价”是什么意思,因为这是一个非常模糊的术语。
如果您的意思是,.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#依靠你来解决这个问题;如果被问到的话,它会愉快地将计算精确到那么精确。
答案 3 :(得分:0)
不幸的是,声明&#34; Math.Abs(x) < double.Epsilon
相当于Math.Abs(x) == 0d
&#34;对于ARM系统来说根本不是真的。
在ARM系统上,Epsilon常量的值太小而无法检测到,因此等于零。
这意味着在ARM系统上,没有非负双值小于Double.Epsilon
,因此表达式Math.Abs(x) < double.Epsilon
只是说{{1}的另一种方式}}