View previous topic :: View next topic |
Author |
Message |
mxkid
Joined: 08 Apr 2008 Posts: 16
|
A strange problem with a float |
Posted: Fri Nov 15, 2013 2:11 pm |
|
|
Hi there,
I have been trying to print a float value to a display and it seems to print the wrong value. For example:
Code: | float set_temperature = 50;
...
printf(lcd_putc, "A:%f",set_temperature); |
I get:
A:49.999999
If i try it with a value of 10 i get 10 on the output.
Sorry if this is a stupid question - i have tried all sorts of things but seem to get the same result. Any help would be great! |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Fri Nov 15, 2013 2:17 pm |
|
|
For floats this is normal. Often a float can't "exactly" store a value. It can be argued that 49.999999 is 50. |
|
|
mxkid
Joined: 08 Apr 2008 Posts: 16
|
|
Posted: Fri Nov 15, 2013 2:26 pm |
|
|
Thanks for the fast reply. What i want to do is take the average of two temperature probes and use that to control an output. So:
Probe 1 = 20 degree's.
Probe 2 = 21 degree's
Average = 20.5 degrees.
I think if i have a look up table i can just "print" the average value without using a float or a calculation.
Cheers - any other ideas welcome |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Nov 15, 2013 2:54 pm |
|
|
Often decimal fixed point numbers with one or two fractional digits are a solution, particularly if they fit a 16 bit variable.
Otherwise rounding and respective format control with float numbers. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Fri Nov 15, 2013 3:41 pm |
|
|
I agree that using an int instead is a much more attactive option. Even declaring a float (and not using it) alarmingly adds to the ROM and RAM used by a project, nevermind the fact that floats are very, very slow to deal with.
Getting back to the int idea....instead of 20 degrees, store 200 in a variable, which actually equals 20.0 degrees. 21 degrees would be 210. Average the two and you have 205, or 20.5 degrees. Much faster to execute, much smaller ROM/RAM "footprint" in code. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Nov 16, 2013 5:44 am |
|
|
and (of course), remember that CCS has the ability to print an int, with a decimal point 'added' using %w.
It is worth realising that (for example), financial calculations _never_ use float, for exactly this reason. Languages designed to work with values where 'cents matter', have libraries to use scaled integers this way.
Also worth saying though, that if using floats, then 'limit the decimals'. So (for instance):
Code: |
printf(lcd_putc, "A:%7.2f",set_temperature+0.005);
|
Will display just two decimal places, and half a digit to the third (undisplayed) decimal, to give rounding.
Repeat again though, just how bulky and slow fp maths is....
Best Wishes |
|
|
mxkid
Joined: 08 Apr 2008 Posts: 16
|
|
Posted: Sat Nov 16, 2013 12:01 pm |
|
|
Hi all,
Thanks for your replies!
Ttelmah,
How would i use %w in my code to produce a decimal point? I have:
Code: | printf(lcd_putc, "S:%Ld", set_temperature); |
I've tried a few variations - if i calculate 'set_temperature' to "205" how can i use %w to display "20.5"? I just tend to get errors. I've looked through the reference manual / other texts and i can't seem to find anything on it. Sorry if i'm being a goonball!
Thanks! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Nov 17, 2013 1:12 am |
|
|
Code: |
printf(lcd_putc, "S:%03.1Lw", set_temperature);
|
The 'w' replaces the 'd'. Needs the 'L' to say a long integer. Then needs the '.1' to say display with one decimal. The 03, means it will display as 0.0, when zero etc. Three 'characters' minimum displayed, and leading zeros, when these characters are zero.
Best Wishes |
|
|
mxkid
Joined: 08 Apr 2008 Posts: 16
|
|
Posted: Sun Nov 17, 2013 2:44 am |
|
|
Hi Ttelmah,
Thanks for the reply. I actually tried that variation but i keep getting:
Error 115 Printf format (%) invalid
My Version is 3.230 so it's pretty old - my spider senses are telling me that this was not supported at the time my compiler was made.
Thanks again - back to the drawing board |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Nov 17, 2013 3:08 am |
|
|
Unfortunately, yes....
I don't think %w, was actually added till about 3.240. Also for the first few versions, it wouldn't accept a 'long'. Wasn't in the 3.226 manual, but had appeared by 3.249.
However you should be able to 'cheat'. Div had been added by then. So:
Code: |
//with the declarations at the top of your code
#include <stdlib.h> //needed for the type declarations
ldiv_t splitter;
//Then when you want to print
splitter=ldiv(set_temperature,10);
printf(lcd_putc, "S:%01Ld.%01Ld", splitter.quot,splitter.rem);
|
More complex, but should give the correct display.
About 179 compiler releases, and 8+ years old version....
Best Wishes |
|
|
mxkid
Joined: 08 Apr 2008 Posts: 16
|
|
Posted: Mon Nov 18, 2013 1:28 pm |
|
|
Hi Ttelmah,
Thanks - that works well. Much better to use int's and insert a decimal point for what i want - happy days |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Mon Nov 18, 2013 1:37 pm |
|
|
Ttelmah wrote: | It is worth realising that (for example), financial calculations _never_ use float, for exactly this reason. Languages designed to work with values where 'cents matter', have libraries to use scaled integers this way.
|
Same can be said for GPS coordinates. My company has GPS receivers on all field equipment and we need the location data to be accurate down to < 3m (usually not a concern if WAAS signals are available).
I designed the GPS -> our system interface device and another engineer here (pure comp sci education) then integrated the data into a mapping database. First attempt was horrible - accuracy was on the order of a km, not a few meters. Turns out he was taking the integer location data and loading it into a float and going from there. Once I told him to treat the data as an int, our accuracy suddenly increased by several orders of magnitude. |
|
|
|