将双精度类型传递给 ceil 会导致 GCC 中不同优化级别的不同值

发布于 2024-09-11 05:08:18 字数 873 浏览 6 评论 0原文

下面,result1 和 result2 变量值报告不同的值,具体取决于是否 您在 GCC 4.2.1 和 GCC 3.2.0 上使用 -g 或 -O 编译代码(我没有尝试更新的 GCC 版本):

double double_identity(double in_double)
{
    return in_double;
}

...

double result1 = ceil(log(32.0) / log(2.0));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result1==" << result1 << std::endl;

double result2 = ceil(double_identity(log(32.0) / log(2.0)));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result2==" << result2 << std::endl;

仅当使用 -g 编译时, result1 和 result2 == 5 ,但如果相反我使用 -OI get result1 == 6 和 result2 == 5 进行编译。

这似乎是编译器如何进行优化的差异,或者与内部 IEEE 浮点表示有关,但我很好奇到底是如何实现的就会出现这种差异。我希望尽可能避免查看汇编器。

上面是用 C++ 编译的,但我认为如果使用 printfs 将其转换为 ANSI-C 代码,同样会成立。

上述差异发生在 32 位 Linux 上,但不会出现在 64 位 Linux 上。

谢谢 背景

Below, the result1 and result2 variable values are reporting different values depending upon whether or not
you compile the code with -g or with -O on GCC 4.2.1 and on GCC 3.2.0 (and I have not tried more recent GCC versions):

double double_identity(double in_double)
{
    return in_double;
}

...

double result1 = ceil(log(32.0) / log(2.0));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result1==" << result1 << std::endl;

double result2 = ceil(double_identity(log(32.0) / log(2.0)));
std::cout << __FILE__ << ":" << __LINE__ << ":" << "result2==" << result2 << std::endl;

result1 and result2 == 5 only when compiling using -g, but if instead I compile with -O I get result1 == 6 and result2 == 5.

This seems like a difference in how optimization is being done by the compiler, or something to do with IEEE floating point representation internally, but I am curious as to exactly how this difference occurs. I'm hoping to avoid looking at the assembler if at all possible.

The above was compiled in C++, but I presume the same would hold if it was converted to ANSI-C code using printfs.

The above discrepancy occurs on 32-bit Linux, but not on 64-bit Linux.

Thanks
bg

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

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

发布评论

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

评论(1

爱要勇敢去追 2024-09-18 05:08:18

在 x86 上,启用优化后,子表达式的结果在用作较大表达式的一部分之前不一定存储在 64 位内存位置中。

由于 x86 的标准浮点寄存器是 80 位,这意味着在这种情况下,可以使用额外的精度。如果您将这个特别精确的值除以(或乘以)另一个值,则精度提高的效果可以放大到肉眼可以感知的程度。

Intel 的 64 位处理器使用 SSE 寄存器进行浮点数学运算,而这些寄存器没有额外的精度。

您可以使用 g++ 标志 可以解决这个问题。

On x86, with optimizations on, the results of subexpressions are not necessarily stored into a 64-bit memory location before being used as part of a larger expression.

Because x86's standard floating-point registers are 80 bits, this means that in such cases, extra precision is available. IF you then divide (or multiply) that especially-precise value by another, the effects of the increased precision can magnify to the point where they can be perceived by the naked eye.

Intel's 64-bit processors use SSE registers for floating point math, and those registers don't have the extra precision.

You can play around with g++ flags to fix this if you really care.

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