cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble printing float number normally

chenping
Associate II
Posted on April 03, 2015 at 21:15

Attached is my modification of tiny_printf.c where I simply added float printing function (case 'f'). By default, the decimal points is 6.

Below are floats I tried to print:

Float                                                      Output

0.01                                                          0.10000

0.1                                                            0.100000

2.001                                                        2.1000

2.127                                                        2.127000

4.669                                                        4.669000

Highlighted part of my tiny_printf.c :

unsigned short precision = 6;

static const unsigned long dv[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 };

static const float p[] = {0.0,10.0,100.0,1000.0,10000.0,100000.0,1000000.0,10000000.0,100000000.0,1000000000.0 };

case '.':

                  precision = *(++fmt) - '0';

                  if(!(precision >= 0 && precision <= 6))

                      precision = 6;

                  ++fmt;

 case 'f':

                {

                    float fval;

                    fval = va_arg(va, double);

                    if(fval < 0.0) {

                        fval *= -1.0;

                        *buf++ = '-';

                    }

                    long heiltal = (long)fval;

                    ts_itoa(&buf, heiltal, 10);

                    *buf++ = '.';

                    long frac = (long)(fval * p[precision]);

                    long decimal = frac - heiltal * dv[precision];

//                    long decimal = (long)((fval - heiltal) * dv[precision]);

                    ts_itoa(&buf, decimal, 10);

                    precision = 6;

                 }

                 break;

What's the problem with my coding !?

And as I increased the float by timer handler or while loop, for instances,

float ff = 1.28;

ff = ff + 0.01;

the result started getting crazy.. OUTPUT:

1.280000

1.290000

1.300000

1.310000

1.320000

1.330000

1.340000

1.340009

1.350008

1.360007

.

.

.

1.679999

1.690001

1.700002

.

.

The increment wasn't as expected.. Though the difference is small. I suspect it's because the floating point unit is not at its peak because I tried print only the decimal places by multiplying them with 1000, and the result remained the same:

Perhaps you might suggest me a better way of writing it~ Thousand thanks in advance! ^_^

#clive1 #xie-xie-ni-clivel1-!!-thanks-! #xie-xie-ni-clivel1-!!-thanks-! #system-account #neil.andrews
3 REPLIES 3
Posted on April 04, 2015 at 07:23

I might approach/test it like this:

#include <
stdio.h
>
#include <
stdlib.h
>
void test(float fval)
{
char str[16], tmp[16];
char *buf = str;
char *p;
long dec, frac;
unsigned i, precision = 6;
static const unsigned long dv[] = {1, 10, 100, 1000, 10000, 100000, 1000000 };
unsigned long dx = dv[precision];
if (fval < 0.0) // Get positive
{
fval = -fval;
*buf++ = '-';
}
fval *= dx; // Scale
fval += .5; // Round Up
frac = (long)fval;
dec = frac / dx;
frac -= dec * dx;
// Do integer portion
p = tmp + sizeof(tmp);
*--p = 0;
do
{
*--p = '0' + dec % 10;
dec /= 10;
}
while(dec);
while(*p)
*buf++ = *p++;
*buf++ = '.';
// Do fractional portion
p = tmp + sizeof(tmp);
*--p = 0;
for(i=0; i<precision; i++)
{
*--p = '0' + frac % 10;
frac /= 10;
}
while(*p)
*buf++ = *p++;
*buf = 0; // NUL
puts(str);
}
int main(int argc, char **argv)
{
test(0.01);
test(0.1);
test(2.001);
test(2.127);
test(4.669);
test(1.234567);
test(0.123456);
return(1);
}

0.010000
0.100000
2.001000
2.127000
4.669000
1.234567
0.123456

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chenping
Associate II
Posted on April 04, 2015 at 15:27

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6hB&d=%2Fa%2F0X0000000btQ%2FWOKd3ZRbLSPrIMAgItwD03rARveJAfpeeGIhjZHpSsM&asPdf=false
chenping
Associate II
Posted on April 04, 2015 at 15:31

Ah Yes I have tested it using DevC++ and the result is positive.

However, as I tried to modify to apply the coding in my tinyprintf.c , the result doesn't seem so.

I created a case 'f' and placed your coding in it. Assuming the last line of puts(str) has already converted it into string in ascii form, I tried printing with my UART4 like this:

sprintf(buf,''%f'',fval);

USART_PutString(UART4, buf);

The output was none. I wonder why...

Is there any other way of printing it? Thanks for noticing this...