C 打印不带尾随零的浮点/双精度?
有几个问题与此相关,但我没有看到一个正确回答这个问题。我想打印一个浮点数,但我希望小数位数是自适应的。例如:C 打印不带尾随零的浮点/双精度?,c,C,有几个问题与此相关,但我没有看到一个正确回答这个问题。我想打印一个浮点数,但我希望小数位数是自适应的。例如: 0 -> 0 1234 -> 1234 0.1234 -> 0.1234 0.3 -> 0.3 令人烦恼的是,%f说明符只会以固定的精度打印,因此它会向所有未达到该精度的数字添加尾随零。有些人建议使用%g说明符,该说明符适用于一组数字,但对于某些数字,它将切换为科学符号,如下所示: printf("%g", 1000000.0); // pr
0 -> 0
1234 -> 1234
0.1234 -> 0.1234
0.3 -> 0.3
令人烦恼的是,%f
说明符只会以固定的精度打印,因此它会向所有未达到该精度的数字添加尾随零。有些人建议使用%g
说明符,该说明符适用于一组数字,但对于某些数字,它将切换为科学符号,如下所示:
printf("%g", 1000000.0); // prints 1e+06
printf("%.0f", 1000000.0);
如何在不使用不必要的零的情况下打印浮点数,同时仍保持printf对实际包含小数部分的数字的标准精度?您可以这样打印:
printf("%g", 1000000.0); // prints 1e+06
printf("%.0f", 1000000.0);
要获得更详细的答案,请查看。尝试:
printf("%.20g\n", 1000000.0); // = 1000000
这将在20位有效数字后切换为科学记数法(默认为“%g”的6位之后):
但要注意双重精度:
printf("%.20g\n", 0.12345); // = 0.12345000000000000417
printf("%.15g\n", 0.12345); // = 0.12345
使用
snprintf
打印到临时缓冲区,然后手动删除尾随的'0'
字符。没有其他方法既正确又易于实现。问题在于,使用IEEE标准754表示法,浮点值(带有小数部分)永远不会有“尾随零”
尾随零表示对于某些整数x,n,分数值可以写成x/10^n
。但是,对于某些整数x,n,这个标准只能表示形式为x/2^n
因此,您写为0.1234的内容使用字节0x3D 0xFC 0xB9 0x24表示。这是:
Sign = 0
Exponent = 01111011 (which means -4)
Significand: 1.11111001011100100100100
有效位的意思是:1+1/2+1/4+1/8+1/16+0/32+0/64+1/128+0/256+1/512+1/1024+1/2048+0/4096+0/8192+
如果执行此计算,则得到1.974400043487548828125
因此,数字是+1.974400043487548828125*2^(-4)
=0.1234000027179718
(当然,我是用电脑计算的,所以它可能会因为同样的原因关闭…)
如您所见,计算机不想为您决定是否要将此数字切碎在4位(仅)之后,而不是9位(0.123400002)之后。关键是,计算机不认为这个数字是0.1234,后面有无穷多个零
因此,我认为没有比R.更好的方法了。我自己用前面提到的方法编写了一个小函数来实现这一点,这里是一个测试仪。我不能保证它没有bug,但我认为它很好
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *convert(char *s, double x);
int main()
{
char str[3][20];
printf("%s\n%s\n%s\n", convert(str[0], 0),
convert (str[1], 2823.28920000),
convert (str[2], 4.000342300));
}
char *convert(char *s, double x)
{
char *buf = malloc(100);
char *p;
int ch;
sprintf(buf, "%.10f", x);
p = buf + strlen(buf) - 1;
while (*p == '0' && *p-- != '.');
*(p+1) = '\0';
if (*p == '.') *p = '\0';
strcpy(s, buf);
free (buf);
return s;
}
printf(“%.0f”,0.1234)代码>打印“0”。我认为OP不希望这样。“我如何打印浮点数而不需要不必要的零,但也不舍入或截断值?”是打印0的答案,因为is不会在点(分数部分)后打印,这将截断数字,不是吗?@metable如果您打印一个变量,那么该格式将不会更改您的变量。这只是一种打印格式numbers@nabroyan问题明确指出,0.1234应打印为0.1234。这不是你的答案,好主意。但是0.1234
将在IEEE双精度中表示为0.1233999999999580335[…]
。没有尾随的“0”字符。将其四舍五入到机器精度的几倍,然后修剪零。@flyingOwl,snprintf
会为您解决这个问题。这就是重点。如果没有snprintf
,小数点的四舍五入是非常困难的。@R。。从技术上讲,这不是只是截断,而不是舍入吗?还是我遗漏了什么?明白。所以也许我想四舍五入说,小数点后8位,也就是0.12340000。我仍然希望能够打印这个舍入值而不需要额外的零。没有骰子printf(“%.15g”,0.00001)
仍然打印1e-05
@AlexeyFrunze我不认为这是重复的,因为它比我想要的要复杂得多。我可以舍入到几个数字,我只是不想要任何尾随的零。但这正是你所要求的,引用:我如何打印浮点数字而不需要不必要的零,也不需要舍入或截断值?
@AlexeyFrunze啊,我这样做了,我的错。这更多是指类似问题的“答案”,建议使用%.2f
或类似方法。我对它进行了编辑以删除该语言。但现在该语言很模糊。定义对需要它的数字有相当好的精确度
@AlexeyFrunze我指的是printf对实际有小数成分的数字的标准精确度(我相信是小数点后6位)。再说一次,我不希望它是超精确的,我对printf的精确性很好,我只是讨厌后面所有的零。