2015-04-03 12:15 PM
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.andrews2015-04-03 10:23 PM
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
2015-04-04 06:27 AM
2015-04-04 06:31 AM
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...