3

I am working on an embedded application and need to print floating point values. Due to space and other limitations I can only use putchar() for output.

I am trying to create a function that takes a float as parameter and prints it using putchar(). I have a similar function that works for integer values.

void putLong(long x)
{
    if(x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x >= 10) 
    {
        putLong(x / 10);
    }
    putchar(x % 10+'0');
}

How could I make a similar function for floats?

CodeFusionMobile
  • 14,812
  • 25
  • 102
  • 140
  • 2
    Do you happen to know if floats follow the IEEE 754 standard on your embedded system or if they're represented some other way? – Karl Knechtel Dec 05 '10 at 03:44

3 Answers3

2

Here's a possible solution:

typedef enum
{
    DEC1 = 10,
    DEC2 = 100,
    DEC3 = 1000,
    DEC4 = 10000,
    DEC5 = 100000,
    DEC6 = 1000000,

} tPrecision ;

void putFloat( float f, tPrecision p )
{
    long i = (long)f ;
    putLong( i ) ;
    f = (f - i) * p ;
    i = abs((long)f) ;
    if( fabs(f) - i >= 0.5f )
    {
        i++ ;
    }
    putchar('.') ;
    putLong( i ) ;
    putchar('\n') ;
}

You would use it thus:

putFloat( 3.14159f, DEC3 ) ;

which will output "3.142", note the rounding up of the third digit.

If you only need a fixed number of decimal places, you can do away with the precision argument and hard-code it.

When using this function you should be aware that a float only has 6 significant digits of precision, not six decimal places. So if you attempt to print say 123.456 using DEC6 you will get erroneous digits after the third place. Any digits after the 6th significant digit should be ignored, but writing the code to take account of that may be unnecessary in your application or more expensive that you would wish given your constraints.

Clifford
  • 88,407
  • 13
  • 85
  • 165
1

What range of values and accuracy/precision requirements do you need? Printing the exact value of a floating point number in decimal is a very hard problem and requires up to 8 kb or so (I could be off by a few powers of 2; this is off the top of my head) of working space if you support 80-bit or 128-bit long double values. You can probably get by with 1 kb or so if you only support double, and essentially no working space if you just want to print poor approximations.

OK, so here's a really basic version:

void putDouble(double x, int p)
{
    long d;
    if (x<0) {
        putchar('-');
        x=-x;
    }
    d = x;
    putLong(d);
    putchar('.');
    while (p--) {
        x = (x - d) * 10;
        d = x;
        putchar('0'+d);
    }
}

You might want to fix your putLong to handle numbers longer than 2 digits, 2. :-)

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

I think my main approach would be to separate the integer portion of the float's value from the decimal portion.

If you can use some sort of rounding or conversion to integer function, you can use the putLong method you already have to output the integer portion.

Output a decimal point.

Then, subtract that int from the float to isolate the decimal. Now, for the decimal, you can either try to determine the number of places after the decimal, or just multiply by an arbitrarily large power of 10, then strip off extraneous zeroes from the right-hand side of the resulting int and again apply putLong for the result.

I suspect there may be a more efficient or simpler way to do this, but I'm pretty sure this approach will work. Looking up the way a float's bits are used to represent the exponent and value components may also be useful.

DGH
  • 11,189
  • 2
  • 23
  • 24
  • The degree to which this "works" depends a lot on your requirements. It won't work at all for values larger than the max value an integer type can store. – R.. GitHub STOP HELPING ICE Dec 05 '10 at 03:40
  • @R: That is true, however, would you say the basic concept of separating the pre- and post-decimal parts of the value is valid, even if you have to do some extra memory manipulation or use large data types? – DGH Dec 05 '10 at 03:44
  • Perhaps, but it can also work just as well just to keep the location of the decimal point stored in a separate variable. It really depends on what approach you use. – R.. GitHub STOP HELPING ICE Dec 05 '10 at 04:29