检查浮点值是否等于 0 是否安全?
-
20-08-2019 - |
题
我知道通常不能依赖双精度或十进制类型值之间的相等性,但我想知道 0 是否是一种特殊情况。
虽然我可以理解 0.00000000000001 和 0.00000000000002 之间的不精确性,但 0 本身似乎很难搞乱,因为它什么都没有。如果你对任何事情都不精确,那么它就不再是什么了。
但我对这个话题了解不多,所以不宜多说。
double x = 0.0;
return (x == 0.0) ? true : false;
这总是会返回 true 吗?
解决方案
是安全以期望的比较将返回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 );
请记住,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 );
我将离开你运行一个测试,看看实际效果:你更容易记住它的方式
。从MSDN条目 Double.Equals :
<强>精密在比较强>
equals方法应与使用 谨慎,因为两个明显 等效值可以是不相等的,由于 于两个的不同精度 值。下面的示例报告 该双值0.3333和 通过1除以3双返回是 不相等的。
...
,而不是相等的比较, 一个推荐的技术涉及 限定的可接受的裕度 两个值之间的差异(例如 的值中的一个)的0.01%。如果 差的绝对值 两个值之间小于或 等于余量,所不同的 很可能是由于分歧 精度,因此,这些值 很可能是相等的。下列 示例使用此技术来比较 0.33333和1/3,这两个双值 ,以前的代码示例找到 是不相等的。
此外,请参阅 Double.Epsilon 。
当你例如比较不同类型的浮点值实现的问题就来了双比较FLOAT。但具有相同的类型,它不应该是一个问题。
float f = 0.1F;
bool b1 = (f == 0.1); //returns false
bool b2 = (f == 0.1F); //returns true
问题是,程序员有时忘记了隐式类型转换(双浮动)正在发生的比较和它的结果到一个错误。
如果数量被直接分配到所述浮子或双则可以安全要测试的零或可以在53位双键或24个比特的浮子来表示任何的整数。
或者换一种方式,你可以随时分配和整数值为双,然后比较双回同一整数,保证这将是平等的。
您还可以首先通过分配一个整数和具有简单的比较继续通过坚持加,减或由整数乘以工作(假设结果为浮子小于24位ABD 53比特用于双) 。所以,你可以把和双精度浮点数为在一定的控制条件的整数。
没有,这是不确定。所谓的非规范化的值(低于正常),当相比等于0.0,将比较结果为假(非零),而是一个方程中使用将被归一化时(成为0.0)。因此,使用该作为一种机制,以避免除以零也不安全。相反,加1.0,并比较1.0。这将确保所有次归被视为零。
试试这个,你会发现 == 对于 double/float 来说并不可靠。
double d = 0.1 + 0.2;
bool b = d == 0.3;
这里是 回答 来自Quora。
事实上,我认为最好是使用以下代码来对一个双值与0.0:
double x = 0.0;
return (Math.Abs(x) < double.Epsilon) ? true : false;
同为浮动:
float x = 0.0f;
return (Math.Abs(x) < float.Epsilon) ? true : false;