Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing a float in C while avoiding variadic parameter promotion to double

How can I print (that is, to stdout) a float in C without having it be promoted to a double when passed to printf?

The issue here is that variadic functions in C promote all float parameter to double, which incurs two unnecessary conversions. For example, if you turn on -Wdouble-promotion in GCC and compile

float f = 0.f;
printf("%f", f);

you will get

warning: implicit conversion from 'float' to 'double' when passing argument to function

I have relatively little processing power to play with (a 72MHz ARM Cortex-M3), and I am definitely bottlenecking on ASCII output of floating point data. As the architecture lacks a hardware FPU to begin with, having to convert between single and double precision does not help matters.

Is there a way to print a float more efficiently in straight C?

like image 390
Xo Wang Avatar asked Apr 02 '11 08:04

Xo Wang


3 Answers

Avoiding the promotion will not save you anything, since the internal double (or more likely long double) arithmetic printf will perform is going to consume at least 1000x as much time. Accurately printing floating point values is not easy.

If you don't care about accuracy though, and just need to print approximate values quickly, you can roll your own loop to do the printing. As long as your values aren't too large to fit in an integer type, first convert and print the non-fractional part as an integer, then subtract that off and loop multiplying by 10 and taking off the integer part to print the fractional part one digit at a time (buffer it in a string for better performance).

Or you could just do something like:

printf("%d.%.6d", (int)x, (int)((x-(int)x)*1000000));
like image 162
R.. GitHub STOP HELPING ICE Avatar answered Nov 12 '22 21:11

R.. GitHub STOP HELPING ICE


Unfortunately, printf does not have support for handing plain float:s.

This mean that you would have to write your own print function. If you don't need the full expressive power of printf, you could easily convert your floating-point value to an integral part and a part representing a number of decimals, and print out both using integers.

If, on the other hand, you simply would like to get rid of the warning, you could explicitly cast the float to a double.

like image 5
Lindydancer Avatar answered Nov 12 '22 21:11

Lindydancer


I think that doesnt matter - printf is already such a timeconsuming nasty thing, that those conversion should not matter. The time converting float to double should be far less than converting any number to ascii (you should/could profile your code to get there a definitve answer). The only remaining solution would be to write an own custom output routine which converts float->ascii and then uses puts (or similar).

like image 2
flolo Avatar answered Nov 12 '22 21:11

flolo