gpt4 book ai didi

c - 第 15 位数字后小数精度丢失 - PI 错误

转载 作者:行者123 更新时间:2023-11-30 19:54:38 27 4
gpt4 key购买 nike

尝试打印超过 15 位小数的 PI 会导致第 15 位小数之后的小数打印不正确。尽管分配了 30 个正确的十进制值并且使用 long double 来保存该值,但仍然如此。下面的测试用例清楚地显示了该错误。

这是出乎意料的。如果数字中有任何错误,我预计在用尽 IEEE-754 尾数后的第 25 位数字之前不会看到任何错误。这里起作用的规则可能是通过我无法打印回我刚刚分配给下面的 sPI 的相同 30 位数字来解释的。这也会影响打印 math.h 中包含的 M_PI 表示的能力。

#include <stdio.h>

int
main (void) {

// static PI approximation (glibc man 1.17)
long double sPI = 3.14159265358979323846264338327;
char strPI[] = "3.14159265358979323846264338327";

printf ("\n %s (strPI - string - correct)\n", strPI);
printf (" %.29Lf (sPI - long double - INCORRECT)\n\n", sPI);

return (0);
}

输出:

3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979311599796346854 (sPI - long double - INCORRECT)
^^^^^^^^^^^^^^

据推测,此十进制错误适用于任何十进制精度大于 16 位的十进制数。当打印为字符串时,PI 打印得很好(显然),但是当打印为 double 时,小数点精度在小数点后第 15 位之后会下降。是什么原因造成的?

非常有趣,正如建议在浮点文字末尾添加 L 确实有帮助:

 3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979323851280895941 (sPI - long double - INCORRECT)

这提供了 3 位额外的小数点精度。为了清楚起见,这是在旧的 AMD Phenom X4 9850 上的 Linux 3.14.1 内核、gcc 4.8.2 上运行的。(基于 AMD Turion 的笔记本电脑和 Intel P4 给出了相同的结果)

尝试将 quadmath.h__float128 类型分配给 sPI,结果与 long double 相同。还有更多的数字可用,但精度仍然在第 19 位出现故障:

3.14159265358979323846264338327 (strPI - string - correct)
3.1415926535897932385128089594061862 (sPI - long double - INCORRECT)

最佳答案

您没有将“long double”值存储到变量中,而是存储默认的double。编译器读取浮点值,将其存储为默认类型,并且仅“之后”将其转换为long double。当您将其值与“正常”分配的 double 进行比较时,您可以看到这一点。

要提示编译器将常量存储为 long double,请在 float 末尾添加修饰符后缀 Ll点常数。

示例:

#include <stdio.h>

int main (void)
{
// static PI approximation (glibc man 1.17)
double sPI_d = 3.14159265358979323846264338327;
long double sPI = 3.14159265358979323846264338327;
long double sPI_L= 3.14159265358979323846264338327L;
char strPI[] ="3.14159265358979323846264338327";

printf ("\n %s (strPI - string - correct)\n", strPI);
printf (" %.29f (sPI - double)\n", sPI_d);
printf (" %.29Lf (sPI - long double - INCORRECT)\n", sPI);
printf (" %.29Lf (sPI - long double - BETTER)\n", sPI_L);

return 0;
}

输出:

 3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979311599796346854 (sPI - double)
3.14159265358979311599796346854 (sPI - long double - INCORRECT)
3.14159265358979323851280895941 (sPI - long double - BETTER)

另请参阅What is the precision of long double in C++? -- long double 的有效数字不能超过大约 18 位。

关于c - 第 15 位数字后小数精度丢失 - PI 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24485846/

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