Reputation: 1578
I'm looking for a way to print a floating-point number in C, which prints at least one decimal after the dot, but still truncates trailing zeroes, e.g.
double x = 5.0;
printf("<some_format>", x);
// should print 5.0, not 5, and not 5.000000
double y = 5.10;
printf("<same_format>", y);
// should print 5.1, not 5.10, and not 5.100000
double x = 5.1230;
printf("<same_format>", z);
// should print 5.123, not 5.1230
Also, defining a maximum or a fixed number of digits/decimals is exactly what I'm trying to avoid.
Someone knows of one format which accomplishes this with printf
without needing to resort to writing the number to a char buffer and then manually editing this buffer?
Upvotes: 5
Views: 4480
Reputation: 144685
If I understand your question correctly, You want 5.0
to print as 5.0
, 5.10
to print as 5.1
and 5.15
to print as 5.15
...
There is no simple way to achieve this with printf
because the problem is not so simple: 5.10
is represented in C as a double
with a binary encoded fractional part that is an approximation of 5.1
, not an exact representation. If you print it with enough decimals, you will see that it stops producing trailing zeroes:
printf("%.23f", 5.10) -> 5.09999999999999999991326
So your question should be:
How to print a floating point number with at least
n
but at mostp
decimals, eliding trailing zeroes?
This can be achieved by passing p
as the precision field of %f
in sprintf
and running a loop to remove the trailing zeroes beyond n
and trailing period if n
is 0
.
Here is an example:
#include <stdio.h>
int print_double(double value, int n, int p) {
char buf[400];
int dot;
int len;
len = snprintf(buf, sizeof buf, "%.*f", p, value);
if (len >= (int)sizeof(buf)) {
printf("value too large: %g\n", value);
return -1;
}
for (dot = 0; dot < len;) {
if (buf[dot++] == '.')
break;
}
while (len - dot > n && buf[len - 1] == '0')
len--;
if (len > 0 && buf[len - 1] == '.')
len--;
buf[len] = '\0';
printf("%s\n", buf);
return len;
}
int main(int argc, char *argv[]) {
print_double(5.0, 1, 2);
print_double(5.1, 1, 2);
print_double(5.15, 1, 2);
return 0;
}
Upvotes: 6