我知道您通常不能依赖双精度或十进制类型值之间的相等性,但是我想知道0是否是特例。
虽然我可以理解0.00000000000001和0.00000000000002之间的不精确性,但0本身似乎很难弄乱,因为它什么都没有。如果您对某事一无所知,那就再也不是什么了。
但是我对这个话题不太了解,所以我不必说。
double x = 0.0;
return (x == 0.0) ? true : false;
那会永远返回真吗?
我知道您通常不能依赖双精度或十进制类型值之间的相等性,但是我想知道0是否是特例。
虽然我可以理解0.00000000000001和0.00000000000002之间的不精确性,但0本身似乎很难弄乱,因为它什么都没有。如果您对某事一无所知,那就再也不是什么了。
但是我对这个话题不太了解,所以我不必说。
double x = 0.0;
return (x == 0.0) ? true : false;
那会永远返回真吗?
Answers:
它是安全的期望,比较将返回true
当且仅当双变量具有完全相同的值0.0
(在你原来的代码片段,当然,这种情况)。这与==
操作符的语义一致。a == b
表示“ a
等于b
”。
当在纯数学中相同计算的结果为零时,期望某些计算的结果在双精度(或更普遍的是浮点数)算法中为零是不安全的(因为它是不正确的)。这是因为当计算深入时,会出现浮点精度误差-这个概念在数学的实数运算中不存在。
如果您需要进行大量“相等”比较,则最好在.NET 3.5中编写一些辅助函数或扩展方法以进行比较:
public static bool AlmostEquals(this double double1, double double2, double precision)
{
return (Math.Abs(double1 - double2) <= precision);
}
可以通过以下方式使用此方法:
double d1 = 10.0 * .1;
bool equals = d1.AlmostEquals(0.0, 0.0000001);
对于您的简单样本,该测试是可以的。但是呢:
bool b = ( 10.0 * .1 - 1.0 == 0.0 );
请记住,.1是二进制的重复小数,因此无法准确表示。然后将其与以下代码进行比较:
double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away
bool b = ( d1 - 1.0 == 0.0 );
我将让您进行测试以查看实际结果:您更可能以这种方式记住它。
从Double.Equals的MSDN条目中:
比较精度
应谨慎使用Equals方法,因为两个看似等效的值由于两个值的精度不同而可能不相等。下面的示例报告Double值.3333和通过1除以3返回的Double是不相等的。
...
除了比较是否相等外,一种推荐的技术还包括定义两个值之间可接受的差异容限(例如其中一个值的0.01%)。如果两个值之间的差的绝对值小于或等于该裕度,则该差很可能是由于精度上的差异,因此,这些值很可能相等。下面的示例使用此技术比较.33333和1/3,即上一个代码示例发现的两个Double值不相等。
另请参见Double.Epsilon。
x.Equals(y)
的话(1/x).Equals(1/y)
,但是如果不是这种情况x
是0
和y
是1/Double.NegativeInfinity
。这些值声明相等,即使它们的倒数不相等。
x = 0
和重新运行测试y = 0
,但仍然可以找到1/x != 1/y
。
x
和y
类型double
?您如何比较结果以使它们报告不相等?请注意,1 / 0.0不是NaN。
1.0/0.0
它不是应有的NaN,因为限制不是唯一的。其次,无限比较彼此相等,而没有关注无限度)
如果将数字直接分配给浮点数或双精度数,则可以安全地对零或任何可以用53位表示为双精度数或24位浮点数表示的整数进行测试。
或者换一种说法,您总是可以将整数值分配给一个双精度型,然后将双精度型比较回相同的整数,并确保它是相等的。
您还可以通过分配一个整数开始,并通过坚持对整数进行加,减或乘以简单比较来继续工作(假设浮点数的结果小于24位,而双精度数的结果小于53位)。因此,您可以在某些受控条件下将浮点数和双精度数视为整数。
实际上,我认为最好使用以下代码将double值与0.0进行比较:
double x = 0.0;
return (Math.Abs(x) < double.Epsilon) ? true : false;
与float相同:
float x = 0.0f;
return (Math.Abs(x) < float.Epsilon) ? true : false;