当前位置:  开发笔记 > 编程语言 > 正文

将浮点值的相等性检查为0是否安全?

如何解决《将浮点值的相等性检查为0是否安全?》经验,为你挑选了5个好方法。

我知道你不能正常依赖双重或十进制类型值之间的相等,但我想知道0是否是特殊情况.

虽然我可以理解0.00000000000001和0.00000000000002之间的不精确,但0本身似乎很难搞砸,因为它什么都没有.如果你对什么都不精确,那就不再是什么了.

但我对这个话题知之甚少,所以我不能说.

double x = 0.0;
return (x == 0.0) ? true : false;

这会永远回归真实吗?



1> Daniel Daran..:

当且仅当double变量具有精确值时(当然,在原始代码片段中是这种情况),可以安全地期望比较将返回.这与运算符的语义一致.意思是" 等于".true0.0==a == bab

当纯数学中相同计算的结果为零时,期望一些计算的结果在双(或更一般地,浮点)算术中为零是不安全的(因为它是不正确的).这是因为当计算出现时,会出现浮点精度误差 - 这个概念在数学中的实数算术中是不存在的.



2> Dirk Vollmar..:

如果你需要进行大量的"相等"比较,那么在.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);


如果这些数字的值彼此非常接近,则可能通过比较double1和double2来获得减法消除错误.我会删除Math.Abs​​并单独检查每个分支d1> = d2 - e和d1 <= d2 + e

3> Joel Coehoor..:

对于您的简单样本,该测试是可以的.但是这个怎么样:

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 );

我会让你去做一个测试,看看实际结果:你更有可能记住它.


实际上,由于某种原因,这会返回true(至少在LINQPad中).

4> Stu Mackella..:

从Double.Equals的MSDN条目:

比较精度

应谨慎使用Equals方法,因为两个明显等效的值可能不相等,因为这两个值的精度不同.以下示例报告Double值.3333和通过除以1而返回的Double是不相等的.

...

一种推荐的技术不是比较相等性,而是涉及在两个值之间定义可接受的差异裕度(例如其中一个值的0.01%).如果两个值之间的差的绝对值小于或等于该边界,则差异可能是由于精度的差异,因此,值可能相等.以下示例使用此技术比较.33333和1/3,前两个代码示例发现的两个Double值不相等.

另请参阅Double.Epsilon.



5> Yogee..:

当您比较不同类型的浮点值实现时,例如将float与double进行比较,就会出现问题.但是同样的类型,它应该不是问题.

float f = 0.1F;
bool b1 = (f == 0.1); //returns false
bool b2 = (f == 0.1F); //returns true

问题是,程序员有时会忘记隐式类型转换(double to float)正在进行比较,结果就是bug.

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有