比较System.Double与'0'的正确方法(一个数字,整数?)


87

抱歉,这可能是一个简单的愚蠢问题,但是我需要确定一下。

我有这个if表情

void Foo()
{
    System.Double something = GetSomething();
    if (something == 0) //Comparison of floating point numbers with equality 
                     // operator. Possible loss of precision while rounding value
        {}
}

那表达等于吗

void Foo()
{
    System.Double something = GetSomething();
    if (something < 1)
        {}
}

?因为那样我可能会遇到问题,请输入if一个值为0.9的。


3
// Comparison of floating point numbers with equality // operator. 您真的需要指定吗?:)
乔治·约翰斯顿,

1
哎呀 有很多介于0和1之间的值。为什么不只是对其进行测试并自己看看呢?
Igby Largeman

12
我只是写了和Resharper一样的文字,以表明我的重点在哪里。
radbyx 2011年

@Charles:另外,还有很多小于0的数字。–
Brian

Answers:


114

好吧,您需要多接近零的值?如果您经过许多浮点运算,这些浮点运算的“无限精度”可能会导致0,那么最终结果可能“非常接近”于0。

通常,在这种情况下,您需要提供某种epsilon,并检查结果是否在该epsilon内:

if (Math.Abs(something) < 0.001)

您应使用的epsilon特定于应用程序-它取决于您正在执行的操作。

当然,如果结果应该恰好为零,那么简单的相等检查就可以了。


实际上,我需要它精确地为零,这看起来如何?我寻找Double.Zero,但知道运气。有不变的权利吗?顺便说一句,谢谢,我现在得到了epsilon部分:)
radbyx 2011年

24
@radbyx:只需使用== 0。你那里有一个字面量-这是相当恒定的:)
Jon Skeet

35

如果something不是根据其他操作的结果分配的,something = 0则最好使用:

if(Math.Abs(something) < Double.Epsilon)
{
//do something
}

编辑:此代码是错误的。Epsilon是最小的数字,但不是十分零。当您希望将一个数字与另一个数字进行比较时,您需要考虑什么是可接受的公差。假设您不关心任何超出.00001的内容。那就是您要使用的号码。该值取决于域。但是,几乎可以肯定从来没有Double.Epsilon。


2
这不解决四舍五入问题,例如Math.Abs(0.1f - 0.1d) < double.Epsilonfalse
托马斯,临近Lule

6
Double.Epsilon太小,无法进行这种比较。Double.Epsilon是double可以表示的最小正数。
埃夫让尼·纳博科夫

3
这没有任何意义,因为它实际上与与0进行比较相同。-1
Gaspa79 '17

1
目的是在不使用==的情况下与0的概念进行比较。至少从数学上讲是有意义的。我假设您手头有一个双精度,并且想将其与不带==的零的概念进行比较。如果双精度因任何原因(包括舍入)与0d不同,则测试填充将返回false。此比较似乎对任何双精度型都是有效的,并且仅当该双精度型小于可表示的最小数字时才返回true,这似乎是测试0概念的良好定义,不是吗?
sonatique '17

3
@MaurGi:你错了: double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
奏鸣曲'17年

26

您的 somethingdouble,并且已正确识别该行中的

if (something == 0)

我们double在左侧(lhs)和int右侧(rhs)。

但是现在看来,您好像将lhs转换为int,然后==符号将比较两个整数。那不是那样 double 的转换int明确的,不能“自动”进行。

相反,情况恰恰相反。rhs转换为double,然后该==符号成为两个双精度数之间的相等性检验。此转换是隐式的(自动)。

(有人认为)写更好

if (something == 0.0)

要么

if (something == 0d)

因为这样马上就可以比较两个双打了。但是,这只是样式和可读性的问题,因为编译器在任何情况下都将做同样的事情。

在某些情况下,像乔恩·斯基特(Jon Skeet)的回答一样,引入“宽容”也很重要,但是宽容double也是一样。它可能的当然是1.0,如果你想要的,但它并没有为[最小严格正]整数。


17

如果只想禁止显示警告,请执行以下操作:

if (something.Equals(0.0))

当然,如果您不担心漂移,这只是一个有效的解决方案。我经常这样做以检查是否要除以零。


4

老实说,我不认为这是平等的。考虑您自己的示例:= 0.9或0.0004。第一种情况为FALSE,第二种情况为TRUE。我通常会为我处理这种类型的精度百分比,并在该精度范围内进行比较。取决于您的需求。就像是...

if(((int)(something*100)) == 0) {


//do something
}

希望这可以帮助。


2
某些东西必须完全为零。
radbyx 2011年

所以您很幸运,在这种情况下:)
Tigran

3

这是显示问题的示例(在LinQPad中准备-如果您没有使用,只需使用Console.Writeline代替Dump方法即可):

void Main()
{
    double x = 0.000001 / 0.1;
    double y = 0.001 * 0.01; 

    double res = (x-y);
    res.Dump();
    (res == 0).Dump();
}

x和y在理论上都是相同的,并且等于:0.00001,但是由于缺少“无限精度”,所以这些值略有不同。不幸的是,以false通常的方式与0进行比较时,其返回值还不够。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.