Dav*_*ica -2 c math double-precision
尝试打印多于15个小数位的PI结果会导致在第15个小数位之后打印不正确的小数。尽管分配了30个正确的十进制值,并且使用long double来保留该值。以下测试案例清楚地显示了该错误。
这是出乎意料的。如果数字中有任何错误,我希望在用尽IEEE-754位数之后直到第25位都不会看到任何错误。这里发生的是什么规则可能可以解释,我无法打印回我刚刚分配给以下sPI的相同30位数字。这也会影响打印中M_PI包含的表示形式的能力math.h。
#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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979311599796346854 (sPI - long double - INCORRECT)
^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
大概,此十进制错误将适用于精度大于16的任何十进制数字。当以字符串形式打印时,PI可以正常打印(显然),但是以双精度形式打印时-小数精度会在第15个小数点后下降。是什么原因造成的?
非常有趣,正如建议L在浮点文字的末尾添加一个确实有帮助:
3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979323851280895941 (sPI - long double - INCORRECT)
Run Code Online (Sandbox Code Playgroud)
这提供了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)
Run Code Online (Sandbox Code Playgroud)
您不是将'long double'值存储到变量中,而是默认值double。编译器读取浮点值,将其存储为默认类型,然后仅将其强制转换为long double。将其值与“正常”分配的进行比较时,您会看到此信息double。
要提示编译器将常量存储为a long double,请在修饰符后缀L或l浮点常量的末尾添加。
例:
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
3.14159265358979323846264338327 (strPI - string - correct)
3.14159265358979311599796346854 (sPI - double)
3.14159265358979311599796346854 (sPI - long double - INCORRECT)
3.14159265358979323851280895941 (sPI - long double - BETTER)
Run Code Online (Sandbox Code Playgroud)
另请参见C ++中long double的精度是多少?-您不能期望超过18位有效数字long double。