Originally I was using sprintf with floats always with 2 decimal places using the following code:
static void MyFunc(char* buffer, const float percentage)
{
sprintf(buffer, "%.2f", percentage);
}
One of the percentage values passed was 0x419FFFFF 20 (debugger view), this printed 20.00 into buffer.
I would like instead to show 2 decimal places when not an integer, e.g.
94.74 displayed as 94.74
94.7 displayed as 94.70
0 displayed as 0
5 displayed as 5
100 displayed as 100
I am currently using the following code:
static void MyFunc(char* buffer, const float percentage)
{
int fractional_part = ((percentage - (int)percentage) * 100);
if (0 == fractional_part)
{
sprintf(buffer, "%d", (int)percentage);
}
else
{
sprintf(buffer, "%.2f", percentage);
}
}
Now if 0x419FFFFF 20 (debugger view) is passed, fractional part is calculated as 99. I assume then the sum for fractional_part ends up being (19.99 – 19) * 100 = 99. Why then does the first example not print 19.99 into buffer?
What is the correct solution for my problem?
Yours is a problem of approximation.
Suppose that the percentage is 19.999. Then
fractional_partwould be 99, and the floating point branch would be invoked.But printing 19.999 with two decimals will round it to 20.00, and that is what is printed.
You could always use the floating point branch, in order to get consistent results, and then truncate at ‘.’ if it comes out with ‘.00’. Otherwise, you risk your test and
printf‘s internals to be at odds some time.If you don’t agree with
printf‘s rounding strategy, just useround()on (a copy of)percentageand force your own. Or you might also, e.g.,sprintf()with three digits, and erase the third.And in your specific case (note how my system (Linux x86_64) renders 0x419FFFFF):