我对printf("%f", M_PI)
的行为感到困惑。它打印出3.141593
,但M_PI
为3.14159265358979323846264338327950288
。为什么printf会这样做,如何让它打印出整个浮动。我知道%1.2f
格式说明符,但如果我使用它们,那么我得到一堆未使用的0,输出很难看。我想要浮动的整个精度,但不是额外的任何东西。
答案 0 :(得分:9)
为什么printf会这样做,我怎么能让它打印出来呢 浮。
默认情况下,printf()
函数对6
和%f
格式说明符的精确度为%F
。来自C11(N1570)§7.21.6.1/p8
fprintf函数(强调我的前进):
如果缺少精度,将其视为6 ;如果精度是 零,没有指定#flag,没有小数点字符 出现。如果出现小数点字符,则至少有一位数字 出现在它之前。 值四舍五入到适当的数字 数字。
因此,呼叫等同于:
printf("%.6f", M_PI);
这与“整个浮动”完全不同,至少不像你想象的那样直接。 double
个对象可能以二进制IEEE-754 double precision表示形式存储。您可以使用%a
或%A
格式说明符查看确切的表示形式,将其打印为十六进制浮点数。例如:
printf("%a", M_PI);
将其输出为:
0x1.921fb54442d18p+1
你可以认为是“整个浮动”。
如果您需要的只是“最长十进制近似值”,那么这是有意义的,然后使用DBL_DIG
标题中的<float.h>
。 C11 5.2.4.2.2 / p11 C 浮动类型的特征:
小数位数,q,任何浮点数用 q十进制数字可以用p舍入为浮点数字 基数b数字然后再返回而不更改为q十进制数字
例如:
printf("%.*f", DBL_DIG-1, M_PI);
可以打印:
3.14159265358979
答案 1 :(得分:2)
您可以使用sprintf
将浮动字符打印到具有过度显示精度的字符串,然后使用函数修剪0s,然后使用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--] = '\0';
}
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
,您可能希望截断,而不是简单地修剪零。此外 - 您可能希望确保23.0显示23.0而不是23.(所以也许在小数点后保留一个零)。这主要是概念证明 - 如果你不满意printf
使用sprintf
然后按摩结果。
答案 2 :(得分:1)
将一段文本转换为float或double后,“all”数字不再是有意义的概念。例如,计算机无法知道它转换为“3.14”或“3.14000000000000000275”,并且它们都碰巧产生了相同的浮点数。根据您对所涉及数字精确度的了解,您只需选择适合您任务的位数即可。
如果你想要打印尽可能多的数字,可能会被格式清楚地表示,浮点数约为7位数,双数约为15位数,但这是近似值。