比较浮点 0

发布于 2024-09-26 19:05:19 字数 167 浏览 6 评论 0原文

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

(0.0f == foo * float(0))

无论 foo 的值如何,它都会具有预期的(数学)值吗?

C++ 标准是否定义了行为,还是特定于实现的?

If foo is of float type, is the following expression valid/recommended?

(0.0f == foo * float(0))

Will it have the expected (mathematical) value regardless of foo's value?

Does the C++ standard defines the behavior or is it implementation specific?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一笔一画续写前缘 2024-10-03 19:05:19

嗯,首先,这实际上并不是 C++ 标准的问题。相反,问题在于你的浮点模型标准(最有可能是 IEEE)。

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

真正不安全的是执行其他浮点运算(例如:使用非整数进行加法和减法)并根据 0.0f 检查它们。

Well, first off it isn't really a matter of the C++ standard. Rather what is at issue is your floating-point model standard (most likely IEEE).

For IEEE floats, that is probably safe, as float(0) should result in the same number as 0.0f, and that multiplied by any other number should also be 0.0f.

What isn't really safe is doing other floating point ops (eg: adds and subtracts with non-whole numbers) and checking them against 0.0f.

§对你不离不弃 2024-10-03 19:05:19

正如其他人已经提到的,NaN 和 Infinites 可能会搞砸这种比较。

然而,还有进一步的陷阱:在 C++ 中,您不能依赖于 float 类型的编译时表达式来比较等于运行时计算的相同表达式。

原因是 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;
}

使用一个特定编译器的结果:

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> _

Cheers & hth.,

– 阿尔夫

NaNs and Infinites can screw up such comparisions, as others have already mentioned.

However, there is further pitfall: in C++ you can not rely on a compile time expression of float type, comparing equal to the same expression evaluated at run time.

The reason for that is that C++ allows extended precision for fp computations, in any willy-nilly way. Example:

#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;
}

Results with one particular compiler:

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> _

Cheers & hth.,

– Alf

坦然微笑 2024-10-03 19:05:19

AFAIK,这不一定,它也可能最终非常接近 0。

通常最好与 epsilon 进行比较。我使用这样的函数来进行此类比较:

float EpsilonEqual( float a, float b, float epsilon )
{
    return fabsf( a - b ) < epsilon;
}

AFAIK, It won't necessarily, it could also end up very close to 0.

It is generally best to compare against an epsilon. I use a function like this for doing such comparisons:

float EpsilonEqual( float a, float b, float epsilon )
{
    return fabsf( a - b ) < epsilon;
}
少女净妖师 2024-10-03 19:05:19

通过该特定语句,您可以非常确定结果将为 0 并且比较为 true - 我不认为 C++ 标准实际上规定了它,但任何合理的浮点类型的实现将有 0 像这样工作。

然而,对于大多数其他计算,结果不能完全等于数学上正确结果的文字:

为什么我的数字(例如 0.1 + 0.2)加起来不等于 0.3,并且
相反,我得到了一个奇怪的结果,比如
0.30000000000000004?

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

当代码被编译或者
解释后,你的“0.1”已经是
四舍五入到最接近的数字
格式,这会导致一个小
甚至在之前的舍入误差
计算发生。

阅读浮点指南,了解详细说明以及操作方法与预期值正确比较

With that particular statement, you can be pretty sure the result will be 0 and the comparison be true - I don't think the C++ standard actually prescribes it, but any reasonable implementation of floating point types will have 0 work like that.

However, for most other calculations, the result cannot be expected to be exactly equal to a literal of the mathematically correct result:

Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and
instead I get a weird result like
0.30000000000000004?

Because internally, computers use a
format (binary floating-point) that
cannot accurately represent a number
like 0.1, 0.2 or 0.3 at all.

When the code is compiled or
interpreted, your “0.1” is already
rounded to the nearest number in that
format, which results in a small
rounding error even before the
calculation happens.

Read The Floating-Point Guide for detailed explanations and how to do comparisons with expected values correctly.

雪花飘飘的天空 2024-10-03 19:05:19

我刚刚在 msdn 中读到这篇关于 VisualStudio 中 /fp 选项的文章
链接文本

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

I just read this article in msdn about the /fp option in VisualStudio
link text

Expression optimizations that are
invalid for special values (NaN,
+infinity, -infinity, +0, -0) will not be allowed. The optimizations x-x =>
0, x*0 => 0, x-0 => x, x+0 => x, and
0-x => -x are all invalid for various
reasons (see IEEE 754 and the C99
standard).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文