获取 printf 以打印所有浮点数
Get printf to print all float digits
我对 printf("%f", M_PI)
的行为感到困惑。它打印出 3.141593
,但 M_PI
是 3.14159265358979323846264338327950288
。为什么 printf 这样做,我怎样才能让它打印出整个浮点数。我知道 %1.2f
格式说明符,但如果我使用它们,那么我会得到一堆未使用的 0,并且输出很难看。我想要浮点数的全部精度,但不需要任何额外的东西。
Why does printf do this, and how can I get it to print out the whole
float.
默认情况下,printf()
函数对 %f
和 %F
格式说明符采用 6
的精度。来自 C11 (N1570) §7.21.6.1/p8
fprintf 函数(强调我的前进):
If the precision is missing, it is taken as 6; if the precision is
zero and the # flag is not specified, no decimal-point character
appears. If a decimal-point character appears, at least one digit
appears before it. The value is rounded to the appropriate number
of digits.
因此 call 等同于:
printf("%.6f", M_PI);
这与 "whole float" 完全不同,至少不像您想象的那样直接。 double
objects 很可能以二进制 IEEE-754 double precision 表示形式存储。您可以使用 %a
或 %A
格式说明符查看确切的表示形式,将其打印为十六进制浮点数。例如:
printf("%a", M_PI);
输出为:
0x1.921fb54442d18p+1
你可以认为是 "whole float"。
如果您需要的只是 "longest decimal approximation",这是有道理的,那么使用 <float.h>
header 中的 DBL_DIG
。 C11 5.2.4.2.2/p11 C浮动类型的特性:
number of decimal digits, q, such that any floating-point number with
q decimal digits can be rounded into a floating-point number with p
radix b digits and back again without change to the q decimal digits
例如:
printf("%.*f", DBL_DIG-1, M_PI);
可以打印:
3.14159265358979
一旦将一段文本转换为浮点数或双精度数,"all"数字就不再是一个有意义的概念。例如,计算机无法知道它转换了“3.14”或“3.14000000000000000275”,而它们恰好都产生了相同的浮点数。您只需根据您对所涉及数字精度的了解,选择适合您任务的位数。
如果您想打印尽可能多的数字,可能会被格式清楚地表示,浮点数大约为 7 位数字,双精度数大约为 15 位,但这是一个近似值。
您可以使用 sprintf
以过高的显示精度将浮点数打印到字符串,然后使用函数将 trim 0 传递给 printf
使用 %s
来显示它。概念证明:
#include <math.h>
#include <string.h>
#include <stdio.h>
void trim_zeros(char *x){
int i;
i = strlen(x)-1;
while(i > 0 && x[i] == '0') x[i--] = '[=10=]';
}
int main(void){
char s1[100];
char s2[100];
sprintf(s1,"%1.20f",23.01);
sprintf(s2,"%1.20f",M_PI);
trim_zeros(s1);
trim_zeros(s2);
printf("s1 = %s, s2 = %s\n",s1,s2);
//vs:
printf("s1 = %1.20f, s2 = %1.20f\n",23.01,M_PI);
return 0;
}
输出:
s1 = 23.010000000000002, s2 = 3.1415926535897931
s1 = 23.01000000000000200000, s2 = 3.14159265358979310000
这说明这种方法可能不是您想要的。如果小数部分中连续零的数量超过特定长度(可以作为参数传递给 trim_zeros
),而不是简单地 trimming zeros,您可能想要截断。此外 - 您可能想要确保 23.0 显示为 23.0 而不是 23。(因此可能在小数点后保留一个零)。这主要是概念验证 — 如果您对 printf
不满意,请使用 sprintf
然后修改结果.
我对 printf("%f", M_PI)
的行为感到困惑。它打印出 3.141593
,但 M_PI
是 3.14159265358979323846264338327950288
。为什么 printf 这样做,我怎样才能让它打印出整个浮点数。我知道 %1.2f
格式说明符,但如果我使用它们,那么我会得到一堆未使用的 0,并且输出很难看。我想要浮点数的全部精度,但不需要任何额外的东西。
Why does printf do this, and how can I get it to print out the whole float.
默认情况下,printf()
函数对 %f
和 %F
格式说明符采用 6
的精度。来自 C11 (N1570) §7.21.6.1/p8
fprintf 函数(强调我的前进):
If the precision is missing, it is taken as 6; if the precision is zero and the # flag is not specified, no decimal-point character appears. If a decimal-point character appears, at least one digit appears before it. The value is rounded to the appropriate number of digits.
因此 call 等同于:
printf("%.6f", M_PI);
这与 "whole float" 完全不同,至少不像您想象的那样直接。 double
objects 很可能以二进制 IEEE-754 double precision 表示形式存储。您可以使用 %a
或 %A
格式说明符查看确切的表示形式,将其打印为十六进制浮点数。例如:
printf("%a", M_PI);
输出为:
0x1.921fb54442d18p+1
你可以认为是 "whole float"。
如果您需要的只是 "longest decimal approximation",这是有道理的,那么使用 <float.h>
header 中的 DBL_DIG
。 C11 5.2.4.2.2/p11 C浮动类型的特性:
number of decimal digits, q, such that any floating-point number with q decimal digits can be rounded into a floating-point number with p radix b digits and back again without change to the q decimal digits
例如:
printf("%.*f", DBL_DIG-1, M_PI);
可以打印:
3.14159265358979
一旦将一段文本转换为浮点数或双精度数,"all"数字就不再是一个有意义的概念。例如,计算机无法知道它转换了“3.14”或“3.14000000000000000275”,而它们恰好都产生了相同的浮点数。您只需根据您对所涉及数字精度的了解,选择适合您任务的位数。
如果您想打印尽可能多的数字,可能会被格式清楚地表示,浮点数大约为 7 位数字,双精度数大约为 15 位,但这是一个近似值。
您可以使用 sprintf
以过高的显示精度将浮点数打印到字符串,然后使用函数将 trim 0 传递给 printf
使用 %s
来显示它。概念证明:
#include <math.h>
#include <string.h>
#include <stdio.h>
void trim_zeros(char *x){
int i;
i = strlen(x)-1;
while(i > 0 && x[i] == '0') x[i--] = '[=10=]';
}
int main(void){
char s1[100];
char s2[100];
sprintf(s1,"%1.20f",23.01);
sprintf(s2,"%1.20f",M_PI);
trim_zeros(s1);
trim_zeros(s2);
printf("s1 = %s, s2 = %s\n",s1,s2);
//vs:
printf("s1 = %1.20f, s2 = %1.20f\n",23.01,M_PI);
return 0;
}
输出:
s1 = 23.010000000000002, s2 = 3.1415926535897931
s1 = 23.01000000000000200000, s2 = 3.14159265358979310000
这说明这种方法可能不是您想要的。如果小数部分中连续零的数量超过特定长度(可以作为参数传递给 trim_zeros
),而不是简单地 trimming zeros,您可能想要截断。此外 - 您可能想要确保 23.0 显示为 23.0 而不是 23。(因此可能在小数点后保留一个零)。这主要是概念验证 — 如果您对 printf
不满意,请使用 sprintf
然后修改结果.