View previous topic :: View next topic |
Author |
Message |
philippe320
Joined: 30 Dec 2005 Posts: 11
|
Math accuracy |
Posted: Fri Dec 30, 2005 11:43 am |
|
|
Hello,
thank you to welcome me in your forum, it's my first message here.
Here is my code on an 16F876
Code: |
#include <16F876.h>
#include <math.h>
#ORG 0x1F00,0x1FFF {} //for the 8k 16F876
// #org 0x1F00, 0x1FFF void loader16F877(void) {} //for the 8k 16F876/7
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay(clock=4000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
char ligne[50];
void main() {
float valeur;
float increment=1.0;
int16 i;
valeur=PI;
for (i=0;i<600;i++){
sprintf(ligne,"(%3.9f)",valeur);
puts(ligne);
valeur=valeur+increment;
} //for
} //main
|
And here is the end of the output I get
(590.141588449)
(591.141590476)
(592.141589522)
(593.141591548)
(594.141593575)
(595.141589641)
(596.141591668)
(597.141590714)
(598.141592741)
(599.141594767)
(600.141587853)
(601.141589879)
(602.141588926)
Why do I get such unaccurate results ?
I could admit an unaccuracy on the last digit, but not to have quite a random generator
Can someone explain me what to do ?
Thank you in advance for your reply
Philippe |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 30, 2005 12:08 pm |
|
|
As a work around, try using %g instead of %f. |
|
|
philippe320
Joined: 30 Dec 2005 Posts: 11
|
|
Posted: Fri Dec 30, 2005 1:36 pm |
|
|
I'm getting this error :
*** Error 115 "C:\Test 2.c" Line 40(22,28): Printf format (%) invalid
Philippe |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 30, 2005 1:43 pm |
|
|
You probably don't have the latest version of the compiler.
What is your version ? Look at the top of the .LST file
in your project folder, to find the version. |
|
|
philippe320
Joined: 30 Dec 2005 Posts: 11
|
|
Posted: Fri Dec 30, 2005 1:48 pm |
|
|
My version is 3.221 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 30, 2005 2:57 pm |
|
|
In the floating point format that is used by CCS, you only have about
7 digits of accuracy.
http://www.ccsinfo.com/faq/?21
See the Floating Point section on the following web page, which
shows 7.2 digits of resolution for the 32-bit floating point format:
http://www.bknd.com/cc5x/math.shtml
So you should modify your sprintf() statement to do this:
sprintf(ligne, "%3.4f",valeur);
Then you will get this result, which display the 7 digits of resolution
that are available:
Quote: |
590.1415
591.1415
592.1415
593.1415
594.1415
595.1415
596.1415
597.1415
598.1415
599.1415
600.1415
601.1415
602.1415 |
But that result is not rounded properly. To do that, modify the
sprintf statement to this:
sprintf(ligne, "%3.4f",valeur + .00005);
Then it displays:
Quote: |
590.1416
591.1416
592.1416
593.1416
594.1416
595.1416
596.1416
597.1416
598.1416
599.1416
600.1416
601.1416
602.1416 |
|
|
|
philippe320
Joined: 30 Dec 2005 Posts: 11
|
|
Posted: Sat Dec 31, 2005 6:28 am |
|
|
Thank you for your reply
ok, but I haven't such an accuracy, only 4 bits ....
Quote: |
See the Floating Point section on the following web page, which
shows 7.2 digits of resolution for the 32-bit floating point format:
http://www.bknd.com/cc5x/math.shtml
|
ok, interesting, but refering to another compiler, so ....
with your rounding method, I get really 4 bits, but you understand my goal to get the 7 bits precision of the float format.
Is there no hope to get them ?
Philippe |
|
|
Ttelmah Guest
|
|
Posted: Sat Dec 31, 2005 9:32 am |
|
|
Er. You have them already.
The digits in front of the decimal point are also part of the total accuracy.
With three digits in front of the DP, only about four after the DP, are useable.
Don't confuse 'bits' with decimal digits either. Three 'bits' would only be 1 part in eight possible accuracy. You have about 24'bits'of accuracy.
Best Wishes |
|
|
philippe320
Joined: 30 Dec 2005 Posts: 11
|
|
Posted: Sun Jan 01, 2006 9:36 am |
|
|
Best whishes also
So, I'm really disappointed
When you're running this code under a windows compiler
(VC+ 6 in my case), you get all your 7 digits of range.
Surprised that CCS doesn't give me them.
Best regards
Philippe |
|
|
Ttelmah Guest
|
|
Posted: Sun Jan 01, 2006 9:55 am |
|
|
philippe320 wrote: | Best whishes also
So, I'm really disappointed
When you're running this code under a windows compiler
(VC+ 6 in my case), you get all your 7 digits of range.
Surprised that CCS doesn't give me them.
Best regards
Philippe |
VC6, defaults to using a double (8byte float). Try using a 'single', instead of a 'float'. The results will be fractionally better still, because you have a chip containing typically perhaps 1000 to 10000* the actual number of gates involved in the PIC, and able therefore to implement some rather better checking internally, but you will find the results are not that different.
Best Wishes |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Mon Jan 02, 2006 8:43 am |
|
|
What is it you are calculating? There are not that many physical quantities that can practically be know to better than one part in ten million. Money, academic physical constants, and some high accuracy land sureying are the only exceptions that come to mind.
If you were to build a modern airplane using a value of Pi that was off by one part in a million, no one, not even the people in the Quality Control, could tell the difference! _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
|