|
|
View previous topic :: View next topic |
Author |
Message |
Max Guest
|
Problem with Floating Point |
Posted: Sat Jan 11, 2003 7:55 am |
|
|
<font face="Courier New" size=-1>I use a function for generate the temperature from uV.
float TcK(float Eu)
{
float Tk;
unsigned int i;
Tk=0;
if (Eu <= 0)
{
for(i=0;i<=8;i++)
Tk=Tk+(T0[i]* pow(Eu,i));
return Tk;
}
If I use :
for (t=0;t<10000;t+=500)
{
printf("\%f \%f\r",t,TcK(t));
printf("\%4.2f \%4.2f\r",t,TcK(t));
the output of t is wrong. For example for t=5000 the display show 4999.999857. Why I have this type of conversion?
With this number my routine doesn't work good.
Thank Max
___________________________
This message was ported from CCS's old forum
Original Post ID: 10612 |
|
|
TSchultz
Joined: 08 Sep 2003 Posts: 66 Location: Toronto, Canada
|
RE: Problem with Floating Point |
Posted: Sat Jan 11, 2003 8:57 am |
|
|
This is a common problem with floating point and is not unique to the PIC or this compiler.
The floating point number is single precision and is comprised of 4 bytes. The CCS compiler uses the PIC format for a float, which differs slightly from the IEEE format but alows for an easier test of zero values. The float format used by the compiler can be found on page 168 in the manual and if you take a look at it you will see that there is a finite resolution (1 bit in 23) which is then multiplied by your exponent.
-Troy
:=<font face="Courier New" size=-1>I use a function for generate the temperature from uV.
:=float TcK(float Eu)
:={
:= float Tk;
:= unsigned int i;
:= Tk=0;
:= if (Eu <= 0)
:= {
:= for(i=0;i<=8;i++)
:= Tk=Tk+(T0[i]* pow(Eu,i));
:= return Tk;
:= }
:=If I use :
:=for (t=0;t<10000;t+=500)
:= {
:= printf("\%f \%f\r",t,TcK(t));
:= printf("\%4.2f \%4.2f\r",t,TcK(t));
:=
:=the output of t is wrong. For example for t=5000 the display show 4999.999857. Why I have this type of conversion?
:=With this number my routine doesn't work good.
:=Thank Max
___________________________
This message was ported from CCS's old forum
Original Post ID: 10613 |
|
|
nilsener Guest
|
Re: Problem with Floating Point |
Posted: Sat Jan 11, 2003 9:02 am |
|
|
Dear,
I think you can not change anything that the result of ten additions of 500.0 is 4999.999857. It depends on the accuracy of floats, I guess it is 23 Bit, a PIC can not calculate floats as accurate like you but very much faster. However, what do you see on your display is the real result of the calculation and not a type conversion of the printf function.
If you want to see 5000 on your display try something like this:
printf("\%4.0f \%4.2f\r",(t+0.5),TcK(t));
Have a look to floor(value) and ceil(value), you can use it for an exacter round algorithm. (Needs math.h)
regards nilsener
:=<font face="Courier New" size=-1>I use a function for generate the temperature from uV.
:=float TcK(float Eu)
:={
:= float Tk;
:= unsigned int i;
:= Tk=0;
:= if (Eu <= 0)
:= {
:= for(i=0;i<=8;i++)
:= Tk=Tk+(T0[i]* pow(Eu,i));
:= return Tk;
:= }
:=If I use :
:=for (t=0;t<10000;t+=500)
:= {
:= printf("\%f \%f\r",t,TcK(t));
:= printf("\%4.2f \%4.2f\r",t,TcK(t));
:=
:=the output of t is wrong. For example for t=5000 the display show 4999.999857. Why I have this type of conversion?
:=With this number my routine doesn't work good.
:=Thank Max
___________________________
This message was ported from CCS's old forum
Original Post ID: 10614 |
|
|
john cutler
Joined: 06 Sep 2003 Posts: 82 Location: Hot Tub, California
|
Re: Problem with Floating Point |
Posted: Sat Jan 11, 2003 9:54 am |
|
|
I posted a few days ago - no one responded - different float problem - MPLAB6 displays float incorrectly in watch windows, but the actual value of the floats is ok. If I cast the float variable to an int16, it displays ok in the watch window. Anyone have any ideas?
:=<font face="Courier New" size=-1>I use a function for generate the temperature from uV.
:=float TcK(float Eu)
:={
:= float Tk;
:= unsigned int i;
:= Tk=0;
:= if (Eu <= 0)
:= {
:= for(i=0;i<=8;i++)
:= Tk=Tk+(T0[i]* pow(Eu,i));
:= return Tk;
:= }
:=If I use :
:=for (t=0;t<10000;t+=500)
:= {
:= printf("\%f \%f\r",t,TcK(t));
:= printf("\%4.2f \%4.2f\r",t,TcK(t));
:=
:=the output of t is wrong. For example for t=5000 the display show 4999.999857. Why I have this type of conversion?
:=With this number my routine doesn't work good.
:=Thank Max
___________________________
This message was ported from CCS's old forum
Original Post ID: 10615 |
|
|
Sherpa Doug Guest
|
Re: Problem with Floating Point |
Posted: Mon Jan 13, 2003 8:48 am |
|
|
:=the output of t is wrong. For example for t=5000 the display show 4999.999857. Why I have this type of conversion?
:=With this number my routine doesn't work good.
:=Thank Max</font>
This is a classic problem with floating point. It is pretty much independant of the chip or the compiler. You just need to round off to the precision you require as Nilsener mentions.
This is one reason I avoid floats if at all possible. Note that banking software NEVER uses floats. Interest rates are not calculated using exponentials. It is all done with lookup tables and +-*/. Money is too valuable to have little bits of it lost or created in the computers!
___________________________
This message was ported from CCS's old forum
Original Post ID: 10649 |
|
|
R.J.Hamlett Guest
|
Re: Problem with Floating Point |
Posted: Mon Jan 13, 2003 11:52 am |
|
|
:=:=the output of t is wrong. For example for t=5000 the display show 4999.999857. Why I have this type of conversion?
:=:=With this number my routine doesn't work good.
:=:=Thank Max</font>
:=
:=This is a classic problem with floating point. It is pretty much independant of the chip or the compiler. You just need to round off to the precision you require as Nilsener mentions.
:=
:=This is one reason I avoid floats if at all possible. Note that banking software NEVER uses floats. Interest rates are not calculated using exponentials. It is all done with lookup tables and +-*/. Money is too valuable to have little bits of it lost or created in the computers!
:=
Which is also another reason why a lot of people here have in the past recommended 'scaled integer' types to solve this sort of problem. If (for instance), you need to have accurate arithmetic for numbers with a maximum value of about one million, you could use a 32bit signed integer, and 'scale' the result, and all incoming values by a factor of 1000. This then allows a 'precision' to .001, and arithmetic without rounding errors, up to +/-2.1 million. Many languages offer this type of arithmetic (for instance Visual Basic, has a 'currency' data type handled exactly this way, for this very reason. It is also worth realising that this type of arithmetic is quicker than floating point.
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 10654 |
|
|
rtrescott Guest
|
floating point problem |
Posted: Wed Aug 10, 2005 12:45 am |
|
|
The printf result output is indeed in error, and it IS compiler dependant. The format of a PIC float is different than IEEE, but it can be translated properly, and without the loss of precision in the displayed output. Microchip has no problem displaying the proper number in the MPLAB watch window, so it must be compiler specific. I have other compilers that use 32 bit floats and there are no output errors. As I recall, the ANSI IEEE spec describes the function of one particular bit that solves the rounding error problem.
CCS engineers need to go back into their code and repair the libraries that work with floating point conversions and resulting outputs. |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
Re: floating point problem |
Posted: Wed Aug 10, 2005 6:53 am |
|
|
rtrescott wrote: | The printf result output is indeed in error, and it IS compiler dependant. The format of a PIC float is different than IEEE, but it can be translated properly, and without the loss of precision in the displayed output. Microchip has no problem displaying the proper number in the MPLAB watch window, so it must be compiler specific. I have other compilers that use 32 bit floats and there are no output errors. As I recall, the ANSI IEEE spec describes the function of one particular bit that solves the rounding error problem.
CCS engineers need to go back into their code and repair the libraries that work with floating point conversions and resulting outputs. |
Hard to say exactly without delving in to the CCS floating point representation, but it is completely impossible to represent every floating point number exactly. The ANSI IEEE spec can't deal with this. That said, "standard" floats can represent positive and negative integers exactly, to some very high number. I don't know about the Microchip 32 bit float format that CCS uses, though. Hi-tech uses IEEE754 format. Since the compilers use different float formats differences should not be surprising.
I recommend http://www.validlab.com/goldberg/paper.ps for a pretty good discussion. http://www.mathworks.com/company/newsletter/pdf/Fall96Cleve.pdf
describes how these problems pop up in matlab, which uses double precision floats by default.
Bottom line, when dealing with floats, care is needed. A fine policy is never to do direct equality testing on floats, unless you know what you're doing. When displaying a float, filter your data through some rounding function and display with appropriate precision. Also, use integers when to do so is more appropriate (as it seems to be for "t" in the example posted) |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
The difference has two sources |
Posted: Wed Aug 10, 2005 2:39 pm |
|
|
I'll use the word difference since there is no error in a mathematical sense.
The first source of any difference occurs whether it is a base 10 float or any other base since float means you pick a certain precision window ( a certain number of significant digits). If you can't fit your number into the precision then of course some of the digits in your number are lost ( tuncated)
The second source of any difference is changing between number bases.
0.1 or 1/10 in decimal can be expressed exactly but the same value 1/10 in decimal cannot be expressed in binary exactly no matter how many bits you care to go to. It's mathematics and no different for 1/3 or .33333.... can't be expressed in decimal notation exactly either.
1/3 in base 3 is exact.
For CCS the float mantissa is 23 bits binary so precision is guaranteed to be lost after 23 bits but even 0.1 decimal cannot be accurate in 23 bits binary whereas 0.5 decimal can ( the 0.1 issue is a result of the base change from 10 to 2).
Some wonder why a calcuator gets it right.
A hand held calculator does its arithmetic work in binary coded decimal so it never has the base conversion issue from the get go but it still can't get 1 div 3 right since it has to stop after a certain number of significant digits.
It's all just mathematics and we have to get used to it.
Now the work around is to take advantage of the fact that all integers can be expressed exactly in any base ( two three ten it doesn't matter) but that means you have to keep track of the decimal pt. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|