我知道你不能正常依赖双重或十进制类型值之间的相等,但我想知道0是否是特殊情况.
虽然我可以理解0.00000000000001和0.00000000000002之间的不精确,但0本身似乎很难搞砸,因为它什么都没有.如果你对什么都不精确,那就不再是什么了.
但我对这个话题知之甚少,所以我不能说.
double x = 0.0; return (x == 0.0) ? true : false;
这会永远回归真实吗?
当且仅当double变量具有精确值时(当然,在原始代码片段中是这种情况),可以安全地期望比较将返回.这与运算符的语义一致.意思是" 等于".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而返回的Double是不相等的.
...
一种推荐的技术不是比较相等性,而是涉及在两个值之间定义可接受的差异裕度(例如其中一个值的0.01%).如果两个值之间的差的绝对值小于或等于该边界,则差异可能是由于精度的差异,因此,值可能相等.以下示例使用此技术比较.33333和1/3,前两个代码示例发现的两个Double值不相等.
另请参阅Double.Epsilon.
当您比较不同类型的浮点值实现时,例如将float与double进行比较,就会出现问题.但是同样的类型,它应该不是问题.
float f = 0.1F; bool b1 = (f == 0.1); //returns false bool b2 = (f == 0.1F); //returns true
问题是,程序员有时会忘记隐式类型转换(double to float)正在进行比较,结果就是bug.