C++ 比较浮点0

C++ 比较浮点0,c++,floating-point,equality,C++,Floating Point,Equality,如果foo是float类型,那么以下表达式是否有效/推荐 (0.0f == foo * float(0)) 不管foo的值是多少,它都会有预期的(数学)值吗 C++标准是否定义了行为或是具体实现?< P> AFAIK,它不一定,它也可以非常接近0。 通常最好与ε进行比较。我使用这样的函数来进行此类比较: float EpsilonEqual( float a, float b, float epsilon ) { return fabsf( a - b ) < epsilon;

如果foo是float类型,那么以下表达式是否有效/推荐

(0.0f == foo * float(0))
不管foo的值是多少,它都会有预期的(数学)值吗


C++标准是否定义了行为或是具体实现?

< P> AFAIK,它不一定,它也可以非常接近0。 通常最好与ε进行比较。我使用这样的函数来进行此类比较:

float EpsilonEqual( float a, float b, float epsilon )
{
    return fabsf( a - b ) < epsilon;
}
float EpsilonEqual(float a,float b,float epsilon)
{
返回fabsf(a-b)<>代码>首先,它不是C++标准的问题。相反,问题在于您的浮点模型标准(最有可能是IEEE)

对于IEEE浮点数,这可能是安全的,因为
浮点数(0)
的结果应与0.0f相同,并且乘以任何其他数字也应为0.0f


什么不是真正安全的是做其他浮点运算(例如:加上和减去非整数),并用0.01。.p/>< p>用那个特定语句检查,你可以很确定结果是<代码> 0 < /C> >比较是<代码>真< /代码> -我不认为C++标准实际上规定了它,但是任何浮点类型的合理实现都会使

0
像这样工作

但是,对于大多数其他计算,结果不能完全等于数学上正确的结果:

为什么我的数字,比如0.1+0.2加起来不等于0.3,然后 相反,我得到了一个奇怪的结果,比如 300000000000000004?

因为在内部,计算机使用 格式(二进制浮点)为 不能准确地表示一个数字 比如0.1、0.2或0.3

当代码被编译或 已解释,您的“0.1”已 四舍五入到该表中最接近的数字 格式,这将导致 舍入误差甚至在 计算发生了


请阅读详细解释以及如何正确操作。

我刚刚在msdn中阅读了这篇关于VisualStudio中/fp选项的文章

表达式优化 对于特殊值无效(NaN, +不允许使用无穷大、+0、-0)。优化x-x=> 0,x*0=>0,x-0=>x,x+0=>x,和 0-x=>-x对于各种 原因(参见IEEE 754和C99 标准)


像其他人已经提到的那样,Nan和Infinites会搞砸这种比较

但是,还有一个缺陷:在C++中,您不能依赖于浮点类型的编译时表达式,与运行时评估的相同表达式进行比较。 原因是C++允许以任何任意的方式计算FP计算的扩展精度。例如:

#include <iostream>

// This provides sufficent obfuscation so that g++ doesn't just inline results.
bool obfuscatedTrue() { return true; }

int main()
{
    using namespace std;

    double const    a   = (obfuscatedTrue()? 3.0 : 0.3);
    double const    b   = (obfuscatedTrue()? 7.0 : 0.7);
    double const    c   = a/b;

    cout << (c == a/b? "OK." : "\"Wrong\" comparision result.") << endl;
}
干杯


–Alf

@rursw1如果有standard@rursw1:那不行。假设foo是一个数字(注意:浮点数允许NaN和无穷大)。不确定无穷大*0在数学意义上是否为0:5/0=5/0=>5/0*0=5?@Martin:从数学意义上讲,无穷大*0是未定义的。在IEEE算术中,它是NaN。所以上面的公式不适用于foo是NaN或无穷大的地方!IEEE 754要求-0.0f==+0.0f,即使位值不同。@Michael:这很公平。但这并没有影响到这一点。但是,我将删除引用。将任何有限的IEEE值乘以零将得到零。如果
foo
为无穷大或NaN,则乘法结果为NaN,比较结果为假。@Mike Seymour-好的一点。也许这行是为了检查foo是否是有效的浮点值。我猜这里的注释只是指如果x是NaN,那么x*0就是NaN。你担心
foo*float(0)的结果会有多高的精度
可能与在类型精度下执行的乘法的结果不同?允许编译器生成结果而不是将比较运算符的操作数强制为其编译时类型所生成的结果是否有用(例如,允许对
someFloat==otherFloat/3.0f
进行评估,就好像它是
(double)someFloat==(double)otherFloat/3.0
)?在我看来,在绝大多数情况下后者“更快”,它也会产生无用的结果。@PascalCuoq:asnwer包含一个完整的exqample,带有输出。因此,我“害怕”这个想法“可能”发生,似乎表明您尚未阅读答案。因此,我建议您阅读。@supercat:我只知道一种有用的方法,即异步计算浮点运算的体系结构,其精度高于平台常见的
double
类型。这听起来可能有些深奥,但却很普通PC机工作。它们最初基于三个“协处理器”:8086主处理器,或其8088的8位多路复用总线化身;8087“数学”协处理器,异步处理浮点运算;8089“i/o”协处理器,AFAIK从未使用过。物理包装已经改变,但逻辑设计没有改变。@Cheersandhth.-Alf:我当然认识到允许这种自由可能会使代码“更快”;不过,我看不到表达式
(phaseOfMoon()?(float)f1=(float)(f2/3.0f)?(double)f1=(double)(f2/3.0))是如何表达的
对于任何事情都是有用的,即使它的计算速度是
(float)f1==(float)(f2/3.0f)
的1000倍。
C:\test> g++ --version | find "++"
g++ (TDM-2 mingw32) 4.4.1

C:\test> g++ fp_comparision_problem.cpp & a
"Wrong" comparision result.

C:\test> g++ -O fp_comparision_problem.cpp & a
OK.

C:\test> _