View previous topic :: View next topic |
Author |
Message |
cyberant
Joined: 04 Jun 2007 Posts: 27
|
float problem |
Posted: Fri Aug 22, 2008 2:35 am |
|
|
Hello, I have a float number which i want to print
Code: | float test=0.0424;
printf("test: %.6f\r\n",test); |
------------->
0.042399
why does it print 0.042399? ive tested the same thing with 0.0423 and it prints me the correct 0.042300...
Why not with 0.0424?
Compiler Bug? I have Version 4.032
thanks =) |
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Aug 22, 2008 4:23 am |
|
|
The way a float is stored in memory means it can not accurately represent every possible number. There is an accuracy error involved.
Not sure what that is without looking it up but the value 0.0424 can most accurately be stored in a 32 bit float as 0.42399999.... or something similar.
most numbers within range will be stored corectly but some will only have an accuracy of whatever a 32 bit float gives. |
|
![](templates/subSilver/images/spacer.gif) |
cyberant
Joined: 04 Jun 2007 Posts: 27
|
|
Posted: Fri Aug 22, 2008 6:00 am |
|
|
Wayne_ wrote: | The way a float is stored in memory means it can not accurately represent every possible number. There is an accuracy error involved.
Not sure what that is without looking it up but the value 0.0424 can most accurately be stored in a 32 bit float as 0.42399999.... or something similar.
most numbers within range will be stored corectly but some will only have an accuracy of whatever a 32 bit float gives. |
oh ok so thats right? Never heard of this hmm ok thank you =) |
|
![](templates/subSilver/images/spacer.gif) |
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Fri Aug 22, 2008 6:25 am |
|
|
No, I think this really is a problem. 32-bit floats are supposed to have 24 bits of mantissa and 8 bits of exponent. With 24 bits of mantissa, they can represent numbers to within one part in 16777216. That means they can always be accurate to at least 7 significant figures. It only takes 5 significant figures to distinguish between 0.042400 and 0.042399. And printf is supposed to round to the nearest least significant figure. So that makes this example 100 times less accurate than it really should be. So unless we are dealing with only 15 or 16 bits of mantissa, then we may have a problem with printf() not rounding up. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Fri Aug 22, 2008 7:20 am |
|
|
First, the mantissa, is not 24 bits. It is 23+ bits. The '+', comes because it has a simulated 'extra' bit, as a leading '1'. This though it effectively gives 24 bits for some operations, means that one value has to be discarded (to provide handling for '0'), giving a final result somewhere between 23, and 24 bits. Now, 0.424, represents as 8716597D, which is actually 0.42399999, an error of just 1 part in 42400000, significantly less than the 'worst case' error for a full 24bit mantissa, of 1 in 16777216.
What makes you think printf, is supposed to round?. It never has in normal C, this is why there are rounding functions. If you want to implement 4/5 rounding, you would have to limit the field width, to (say) four digits, and add 0.00004999 to the value. Rounding was added to C#, and C++ implementations, and present in the old AIX C, but only at six digits on the latter, and was not part of the standard printf implementation....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 22, 2008 10:37 am |
|
|
The CCS manual shows this format specifier is available:
Quote: | %g -- Float with rounded decimal |
|
|
![](templates/subSilver/images/spacer.gif) |
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Fri Aug 22, 2008 12:29 pm |
|
|
Ttelmah wrote: | ..What makes you think printf, is supposed to round?. It never has in normal C... |
Every old C compiler I have ever worked with rounds in printf, including Microsoft C 5.1 (1988) and Borland Turbo C for DOS. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Fri Aug 22, 2008 2:05 pm |
|
|
It is a misconception that these are rounding errors. There is no error and rounding is an option so the lack of it isn't an error either. Further rounding has choices nearest lower or upper. They are always issues when moving from one mathematical notation to another. Floating pt uses binary notation so moving from and toward decimal notation creates issues. Decimal 0.5 can be expressed perfectly in binary notation but decimal 0.1 can't. Our brains require notation to grasp numbers other than the first few integers. Our notation is merely a representation of the numbers that exist in this universe.
We are most used to decimal and this leads some to think results using other notations like binary are inaccurate. But decimal is full of similar issues EX one divided by three can't be expressed exactly 0.3333333... stop at anytime and its not exact. Hand held calculators often will do arithmetic in BCD so they never leave decimal notation except for doing trig. This adds to the believe that only decimal notation is exact. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Fri Aug 22, 2008 2:33 pm |
|
|
Hmm.
Have used all the C's you mention, and none defaulted to rounding using %f. They had _options_ to round, but it was not the default behaviour. The reason you appear to get rounding, is that in MS C at least, they handle the printf, using doubles internally.
As PCM programmer says, there is a rounding option for CCS, but if you do a search on apparently losing precision with printf, you will find literally thousands of posts, including quite a lot about the MS and Borland compilers exhibiting this behaviour (but to a much lesser extent).
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Fri Aug 22, 2008 3:59 pm |
|
|
Ttelmah wrote: | ...The reason you appear to get rounding, is that in MS C at least, they handle the printf, using doubles internally.... |
The fact that MS C uses doubles internally in printf does not disqualify the behavior as rounding. Promoting (float)0.04236 to (double)0.04236 does not change the fact that when you printf this number using "%.4f" you get "0.0424" and this is still rounding. If it were not rounding it would print as "0.0423". _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
![](templates/subSilver/images/spacer.gif) |
|