This question already has an answer here:
这个问题已经有了答案:
- Avoid trailing zeroes in printf() 12 answers
- 在printf() 12中避免尾随零。
There are a few questions related to this, but I haven't seen one that correctly answers this question. I want to print a floating-point number, but I want the number of decimal places to be adaptive. As an example:
有一些问题与此相关,但我还没有看到一个问题能正确地回答这个问题。我想打印一个浮点数,但是我想要十进制数的数目是自适应的。作为一个例子:
0 -> 0
1234 -> 1234
0.1234 -> 0.1234
0.3 -> 0.3
Annoyingly, the %f
specifier will only print to a fixed precision, so it will add trailing zeros to all numbers that don't reach that precision. Some have suggested the %g
specifier, which works for a set of numbers, but it will switch to scientific notation for some numbers, like this:
令人恼火的是,%f说明符将只打印到一个固定的精度,因此它将向所有不能达到该精度的数字添加尾随0。有些人建议使用%g的说明符,它适用于一组数字,但它将转换为一些数字的科学符号,像这样:
printf("%g", 1000000.0); // prints 1e+06
How can I print floating-point numbers without the unnecessary zeros, while still maintaining printf's standard accuracy for numbers that actually have fractional components?
如何在不使用不必要的零的情况下打印浮点数,同时仍然保持printf对于具有小数部分的数字的标准精度?
5 个解决方案
#1
8
Use snprintf
to print to a temporary buffer then remove the trailing '0'
characters manually. There is no other way that's both correct and reasonably easy to implement.
使用snprintf打印到临时缓冲区,然后手动删除末尾的“0”字符。没有其他方法既正确又易于实现。
#2
3
Try:
试一试:
printf("%.20g\n", 1000000.0); // = 1000000
This will switch to scientific notation after 20 significant digits (default is after 6 digits for "%g"):
这将在20位有效数字之后转换为科学符号(默认是在“%g”的6位数字之后):
printf("%.20g\n", 1e+19); // = 10000000000000000000
printf("%.20g\n", 1e+20); // = 1e+20
But be careful with double precision:
但是要加倍小心:
printf("%.20g\n", 0.12345); // = 0.12345000000000000417
printf("%.15g\n", 0.12345); // = 0.12345
#3
2
The problem is that using IEEE standard 754 representation, floating point values (with a fractional part) can never have "trailing zeros".
问题是使用IEEE标准754表示,浮点值(有小数部分)永远不会有“尾随零”。
Trailing zeros mean that the fractional value can be written as x/10^n
for some integers x, n. But the only fractions that can be represented by this standard have the form x/2^n
for some integers x, n.
尾随零意味着分数值可以写成x / 10 ^ n对一些整数x,n。但只有分数,可以用这个标准形式整数x x / 2 ^ n,n。
So what you write as 0.1234 is represented using the bytes 0x3D 0xFC 0xB9 0x24. This is:
因此,你所写的0。1234是用字节0x3D 0xB9 0x24表示的。这是:
Sign = 0
Exponent = 01111011 (which means -4)
Significand: 1.11111001011100100100100
The significand means: 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 + 1/2 + 1/4 + 1/8 + 1/16 + 1/ 32 + 0/64 + 1/128 + 0/256 + 1/512 + 1/1024 + 1/2048 + 0/4096 + 0/8192 +…
If you perform this calculation, you get 1.974400043487548828125.
如果执行这个计算,就得到1。974400043487548828125。
So the number is + 1.974400043487548828125 * 2^(-4)
= 0.1234000027179718
所以数量是+ 1.974400043487548828125 * 2 ^(4)= 0.1234000027179718
(I've calculated this using a computer, of course, so it could be off for the same reason...)
(当然,我是用电脑计算出来的,所以它可能会因为同样的原因关闭……)
As you can see, the computer does not want to decide for you that you want to chop this number after 4 digits (only) and not after 9 digits (0.123400002). The point is that the computer doesn't see this number as 0.1234 with an infinite number of trailing zeros.
正如您所看到的,计算机不希望为您决定要在4位(仅)之后而不是在9位(0.123400002)之后删除这个数字。关键是计算机不认为这个数字是0。1234,后面有无数个0。
So I don't think there's a better way than R.'s.
所以我认为没有比R更好的方法了。
#4
0
I wrote a small function to do this myself using the method already mentioned, here it is with a tester. I can't guarantee it's bug free but I think it's fine.
我用前面提到的方法编写了一个小函数来实现这一点,这里有一个测试器。我不能保证它是无缺陷的,但我认为它是好的。
#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;
}
Output:
输出:
0
2823.2892
4.0003423
#5
-1
You can print like this:
你可以这样打印:
printf("%.0f", 1000000.0);
For a more detailed answer, look here.
要获得更详细的答案,请看这里。
#1
8
Use snprintf
to print to a temporary buffer then remove the trailing '0'
characters manually. There is no other way that's both correct and reasonably easy to implement.
使用snprintf打印到临时缓冲区,然后手动删除末尾的“0”字符。没有其他方法既正确又易于实现。
#2
3
Try:
试一试:
printf("%.20g\n", 1000000.0); // = 1000000
This will switch to scientific notation after 20 significant digits (default is after 6 digits for "%g"):
这将在20位有效数字之后转换为科学符号(默认是在“%g”的6位数字之后):
printf("%.20g\n", 1e+19); // = 10000000000000000000
printf("%.20g\n", 1e+20); // = 1e+20
But be careful with double precision:
但是要加倍小心:
printf("%.20g\n", 0.12345); // = 0.12345000000000000417
printf("%.15g\n", 0.12345); // = 0.12345
#3
2
The problem is that using IEEE standard 754 representation, floating point values (with a fractional part) can never have "trailing zeros".
问题是使用IEEE标准754表示,浮点值(有小数部分)永远不会有“尾随零”。
Trailing zeros mean that the fractional value can be written as x/10^n
for some integers x, n. But the only fractions that can be represented by this standard have the form x/2^n
for some integers x, n.
尾随零意味着分数值可以写成x / 10 ^ n对一些整数x,n。但只有分数,可以用这个标准形式整数x x / 2 ^ n,n。
So what you write as 0.1234 is represented using the bytes 0x3D 0xFC 0xB9 0x24. This is:
因此,你所写的0。1234是用字节0x3D 0xB9 0x24表示的。这是:
Sign = 0
Exponent = 01111011 (which means -4)
Significand: 1.11111001011100100100100
The significand means: 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 + 1/2 + 1/4 + 1/8 + 1/16 + 1/ 32 + 0/64 + 1/128 + 0/256 + 1/512 + 1/1024 + 1/2048 + 0/4096 + 0/8192 +…
If you perform this calculation, you get 1.974400043487548828125.
如果执行这个计算,就得到1。974400043487548828125。
So the number is + 1.974400043487548828125 * 2^(-4)
= 0.1234000027179718
所以数量是+ 1.974400043487548828125 * 2 ^(4)= 0.1234000027179718
(I've calculated this using a computer, of course, so it could be off for the same reason...)
(当然,我是用电脑计算出来的,所以它可能会因为同样的原因关闭……)
As you can see, the computer does not want to decide for you that you want to chop this number after 4 digits (only) and not after 9 digits (0.123400002). The point is that the computer doesn't see this number as 0.1234 with an infinite number of trailing zeros.
正如您所看到的,计算机不希望为您决定要在4位(仅)之后而不是在9位(0.123400002)之后删除这个数字。关键是计算机不认为这个数字是0。1234,后面有无数个0。
So I don't think there's a better way than R.'s.
所以我认为没有比R更好的方法了。
#4
0
I wrote a small function to do this myself using the method already mentioned, here it is with a tester. I can't guarantee it's bug free but I think it's fine.
我用前面提到的方法编写了一个小函数来实现这一点,这里有一个测试器。我不能保证它是无缺陷的,但我认为它是好的。
#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;
}
Output:
输出:
0
2823.2892
4.0003423
#5
-1
You can print like this:
你可以这样打印:
printf("%.0f", 1000000.0);
For a more detailed answer, look here.
要获得更详细的答案,请看这里。