## Converting float to string

22 posts / 0 new
Author
Message

Hello again ,

I'm practicing math functions on my Atmega32 and I want to be able to print them on my LCD .

I need to be able to convert floats to strings.
With integers I used itoa and it works fine.
How do I do it with floats?
I cannot find a decent answer for embedded systems.
Some suggestions were to use 'ftoa' but it's not included in the stdlib .

If I were to do this, I might strip the decimal point from the floating point string, remembering the position of the point in the string.

Then use atoi to convert the string to an integer. Next, assign the integer to a floating point variable and then divide by the appropriate power of 10.

There are probably better ways, but that should work.

If we are not supposed to eat animals, why are they made out of meat?

Last Edited: Thu. Aug 15, 2013 - 12:31 PM

AndyG wrote:
If I were to do this, I might strip the decimal point from the floating point string, remembering the position of the point in the string.

Then use itoa to convert the string to an integer. Next, assign the integer to a floating point variable and then divide by the appropriate power of 10.

There are probably better ways, but that should work.

Hmm i don't really understand how assigning the integer to a floating point variable and then dividing by the appropriate power would work , but i'm sure it's just my lack of knowledge .
Also I don't know how I would strip the decimal point.

Thanks alot for the suggestion but I think i'm going to wait for a more efficient one.

Akternatively, this might be useful...

```/*			- ATOF.C -

The ANSI "atof" function.

\$Name: V3_33D \$

*/

#include "ctype.h"
#include "stdlib.h"

double atof (const char *s)
{
#ifdef _INTRINSIC
return (atof(s));
#else
double val, power;
int sign, exp;

while (isspace (*s))
{
s++;
}

if (*s == '-')
{
s++;
sign = -1;
}
else
{
sign = 1;
if (*s == '+')
{
s++;
}
}

val = 0;
while (isdigit (*s))
{
val = val * 10 + (*s++ - '0');
}

power = 1;

if (*s == '.')
{
while (isdigit(*++s))
{
val = val * 10 + (*s - '0');
power = power * 10;
}
}

if (tolower(*s) == 'e')
{
exp = atoi (++s);
while (exp < 0)
{
val /= 10;
exp++;
}
while (exp > 0)
{
val *= 10;
exp--;
}
}

return (sign * val / power);
#endif
}
```

If we are not supposed to eat animals, why are they made out of meat?

My original suggestion would first convert the modified string to an integer, which was a number of powers of ten too big.

If you simply divided the integer to the appropriate power of ten, then because this was integer division, you would lose the part of the number to the right of the decimal point.

Converting to a floating point before the division would result in the division being a floating point one; the part of the number to the right of the decimal point would thus be preserved.

If we are not supposed to eat animals, why are they made out of meat?

I'm not proficient in C coding some of your syntax is unfamiliar to me .
So how would I input a string to that?
Would I call the function with my string as a passed variable?
I'd appreciate some help on that.

Also , I found some other method on youtube .
It works with integers and chars but it doesn't work with floats which is what I need.
My lcd displays a '?' when I use it

```

lcd_init(LCD_DISP_ON);
lcd_clrscr();

char Lcd_result[6];
sprintf(Lcd_result, "%.2f", 12.34 );

lcd_puts(Lcd_result);

```

AndyG wrote:
My original suggestion would first convert the modified string to an integer, which was a number of powers of ten too big.

If you simply divided the integer to the appropriate power of ten, then because this was integer division, you would lose the part of the number to the right of the decimal point.

Converting to a floating point before the division would result in the division being a floating point one; the part of the number to the right of the decimal point would thus be preserved.

EDIT:

I partially understand .I could store 12.52 in an int which would round it off and give me 12. Then I would subtract the float fromthe int to get 0,52 .
Then I could display 12 , then a 'dot'character and then 0.52 multiplied by the 2 orders of power

What do you think ?

`double atof (const char *s)`

The idea is that you pass the (address of the) string to atof and it returns a (double) float.

If we are not supposed to eat animals, why are they made out of meat?

If you have a lot of flash , sprintf might work ... and is flexible enough.

As for why your sprintf is not working, maybe the library you are using does not support floats?

My general approach to using "floating point" numbers on embedded microcontrollers is to use integers internally and convert to a "floating point" format manually.

If we are not supposed to eat animals, why are they made out of meat?

Quote:
The idea is that you pass the (address of the) string to atof and it returns a (double) float.

Ok thanks I'll try it out.

Quote:

Quote:
If you have a lot of flash , sprintf might work ... and is flexible enough.

Yeah I tried using sprintf as I meantioned above, but it does not work.

```lcd_init(LCD_DISP_ON);
lcd_clrscr();

char Lcd_result[6];
sprintf(Lcd_result, "%.2f", 12.34 );

lcd_puts(Lcd_result); ```

But the lcd outputs a '?' character. Is there something wrong with the code?

AndyG wrote:
As for why your sprintf is not working, maybe the library you are using does not support floats?

My general approach to using "floating point" numbers on embedded microcontrollers is to use integers internally and convert to a "floating point" format manually.

Yeah I guessed that It might be something to do with the library .
As for doing it manually , I just wrote up the following code:

```
void printfloat(float a)
{
lcd_clrscr();
int roundoff = a;   // getting rounded integer
float remainder = 0;
int whole_remainder = 0; // declaring remainder variable
remainder = a - roundoff; // calculating remainder

char whole[6];
itoa(roundoff,whole,10);

lcd_puts(whole);
lcd_puts(".");

whole_remainder = remainder*100;

char decimals[6];
itoa(whole_remainder,decimals,10);

lcd_puts(decimals);

}

```

It seems to be working. I can also give it a dynamic precision input which I'm going to write up now.

Thanks for the suggestion AndyG!

Still if someone has another concrete suggestion of doing this an easier way then I'll be happy to hear it !:)
Or maybe how I can make the sprintf work.

Last Edited: Thu. Aug 15, 2013 - 01:04 PM

You are most welcome :)

If we are not supposed to eat animals, why are they made out of meat?

The easy way is to read the "Standard C Library" and the provisions of printf().

Then tick one or two boxes in AS6 Properties. This will link your program with the full f-p printf() library.

Yes, you can go hand-crafting an ftoa() or even use the dstrtof() provided by your avr-gcc library.

David.

Here is the final version with an input to vary the amount of decimal numbers after the point (precision)
Works perfectly

```
void printfloat(float a , int precision)
{
lcd_clrscr();
int roundoff = a;   // getting rounded integer
float remainder = 0;
int whole_remainder = 0; // declaring remainder variable
remainder = a - roundoff; // calculating remainder

char whole[6]; // Numbers before the decimal point
itoa(roundoff,whole,10);

lcd_puts(whole); // writing whole numbers to lcd
lcd_puts("."); // writing a dot to lcd

whole_remainder = remainder*(pow(10,precision));   // multiplying decimals to get a whole number .

char decimals[6];
itoa(whole_remainder,decimals,10);

lcd_puts(decimals); // writing the decimals

}```

Takes about 2.8k of flash together with a math function library and the LCD library and the itoa and all that crap.

david.prentice wrote:
The easy way is to read the "Standard C Library" and the provisions of printf().

Then tick one or two boxes in AS6 Properties. This will link your program with the full f-p printf() library.

Yes, you can go hand-crafting an ftoa() or even use the dstrtof() provided by your avr-gcc library.

David.

Ok thanks for the info , will check it out.

Quote:

But the lcd outputs a '?' character. Is there something wrong with the code?

In your AS6 project look at Solution Explorer. For the project you are working on there is a line that says "Libraries". Right click it then "Add library". Hopefully you will find libm already ticked. Now make sure there's a tick against libprintf_flt as well. Now visit the Properties for the project and under Toolchain-AVR/GNU Linker-General make sure the bottom entry "Use vprintf library" is ticked. Now rebuild and try again. Your ? should now show a floating point number.

Works (no warnings, executes OK once adapted) on a PC.
Have you included ?
Is floating point formatting activated (adds some Ks to your avr executable?)
Edited : redundant with Clawsons.

clawson wrote:
Quote:

But the lcd outputs a '?' character. Is there something wrong with the code?

In your AS6 project look at Solution Explorer. For the project you are working on there is a line that says "Libraries". Right click it then "Add library". Hopefully you will find libm already ticked. Now make sure there's a tick against libprintf_flt as well. Now visit the Properties for the project and under Toolchain-AVR/GNU Linker-General make sure the bottom entry "Use vprintf library" is ticked. Now rebuild and try again. Your ? should now show a floating point number.

Thank you sir , It works now :)

But it takes 800bytes more memory than my custom solution . Nevertheless , i'm Using an atmega32 so plenty left.

Quote:

Nevertheless , i'm Using an atmega32 so plenty left.

Exactly so why bother - by the way did you confirm that libm was ticked? If it isn't that can "cost" a considerable amount of flash space.

The thing with floating point is that you only pay the cost once. For arithmetic functions it costs 700 bytes and for full printf() float support it is about 2-2.5K. ut once those costs are paid you can use the functionality as often as often as you like. It's true that in a 2-4K AVR it's a heavy cost to pay. In anything from 16K onwards it is likely a drop in the ocean.