是Math.Abs​​(X)<double.Epsilon相当于Math.Abs​​(x)的=

2019-10-19 01:03发布

有点轻阅读后, 这篇文章引起了我的兴趣:

我还以为那是,这两个语句是等价的,因为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);
    }

Answer 1:

IL代码似乎蒙上这方面的一些光。

小量是简单地与小数部分为1双号,符号0,0指数零与小数部分为0双号,符号0,指数0。

据http://en.wikipedia.org/wiki/IEEE_754-1985 ,用相同的符号和指数浮点数被序数型标尺相比,这意味着(X <1)是相同的为(x == 0)。

现在,是有可能得到一个零,是不是分数= 0,指数= 0(我们不关心的迹象,有一个Math.Abs​​到位)?



Answer 2:

是的,据我可以告诉他们应该是等价的。 这是因为没有什么区别能有比少小量的幅度也非零。

我只在相关的价值,如double.NaN思想,我测试了一下,并PositiveInfinity时等,结果是一样的。 顺便说一句,double.NaN比较了一些返回false。



Answer 3:

我不知道你所说的“等价”的意思是在这里,因为这是一个相当模糊的术语。

如果你的意思是,将.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#依赖于你明白这一点; 它会很乐意做计算下来到精度,如果要求。



Answer 4:

不幸的是,声明“ Math.Abs(x) < double.Epsilon相当于Math.Abs(x) == 0d ”是不是真的在所有的ARM系统。

MSDN上Double.Epsilon通过阐明,自相矛盾

上ARM系统中,小量常数的值太小,被检测到,因此它相当于零。

这意味着,在ARM系统中,有小于没有非负双值Double.Epsilon ,所以表达式Math.Abs(x) < double.Epsilon只是另一种方式说false



文章来源: Is Math.Abs(x) < double.Epsilon equivalent to Math.Abs(x) == 0d?