gpt4 book ai didi

c++ - 为什么在浮点文字的末尾添加 0 会改变它的舍入方式(可能是 GCC 错误)?

转载 作者:IT老高 更新时间:2023-10-28 12:56:37 25 4
gpt4 key购买 nike

我在我的 x86 VM(32 位)上发现了以下程序:

#include <stdio.h>
void foo (long double x) {
int y = x;
printf("(int)%Lf = %d\n", x, y);
}
int main () {
foo(.9999999999999999999728949456878623891498136799780L);
foo(.999999999999999999972894945687862389149813679978L);
return 0;
}

产生以下输出:

(int)1.000000 = 1
(int)1.000000 = 0

Ideone also produces this behavior.

编译器做了什么来允许这种情况发生?

我在追查为什么下面的程序没有像我预期的那样产生 0 时发现了这个常量(使用 19 个 9 产生了 0 我预计):

int main () {
long double x = .99999999999999999999L; /* 20 9's */
int y = x;
printf("%d\n", y);
return 0;
}

当我试图计算结果从预期变为意外时的值时,我得出了这个问题所涉及的常数。

最佳答案

您的问题是您平台上的 long double 精度不足以存储精确值 0.99999999999999999999。这意味着必须将它的值转换为可表示的值(这种转换发生在程序的翻译过程中,而不是在运行时)。

这种转换可以生成最接近的可表示值,也可以生成下一个更大或更小的可表示值。选择是实现定义的,因此您的实现应该记录它正在使用的。您的实现似乎使用 x87 样式的 80 位 long double,并且正在四舍五入到最接近的值,导致 x 中存储的值为 1.0。


使用 long double 的假定格式(尾数为 64 位),小于 1.0 的最高可表示数字是十六进制:

0x0.ffffffffffffffff

这个值和下一个更高的可表示数字 (1.0) 之间的正好中间的数字是:

0x0.ffffffffffffffff8

你很长的常数 0.9999999999999999999728949456878623891498136799780 等于:

0x0.ffffffffffffffff7fffffffffffffffffffffffa1eb2f0b64cf31c113a8ec...

如果舍入到最接近的值,显然应该向下舍入,但您似乎已经达到编译器使用的浮点表示的某些限制,或者舍入错误。

关于c++ - 为什么在浮点文字的末尾添加 0 会改变它的舍入方式(可能是 GCC 错误)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16831464/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com