Go Down

Topic: BUG: when (double) 2+2 does not equal four (Read 2394 times) previous topic - next topic


I've been playing with calculating sunrise/sunset on an arduino Diecimila.  Consider the following code fragment and the comments:

Code: [Select]
// debugging the J calculation
 double J1 = 2451545;  // ok - got 2451545
 double J2 = 0.0009;   // ok - got 0.0009
 double J3 = 2*M_PI;   // ok - got 6.283185
 double J4 = Lw/J3;    // ok - got 0.215978
 double J5 = J1 + J2;  // wrong - got 2451545.000000
 double J6 = J5 + J4;  // wrong - got 2451545.250000 - even
                       // assuming the bug is in the serial
                       // library println() function, its
                       // still wrong.
 double J7 = J6 + n;   // ok - ignoring previous errors, this
                       // gives 2455513.250000 which is correct.

I might have thought that there was a problem with a cast somewhere, but the bug occurs well after we've established the type of each variable *and* verified correct results.  Interestingly, only addition appears to be affected.  All other operations appear fine.


Nov 14, 2010, 06:07 pm Last Edit: Nov 14, 2010, 06:15 pm by davekw7x Reason: 1
In avr-gcc, doubles are 32-bit floats.  They are good for about seven significant decimal digits.  This has nothing to do with the Serial print function or any other library functions.

I'll look at J5:

How is J5 going to be stored in the machine?

The actual value of J1 + J2 is equal to 2451545.0009, which would require eleven significant decimal digits.

The compiler generates code that stores the 32-bit binary floating point number that is the closest that it can get to 2451545.0009.  That turns out to be 2451545.0

Bottom line: Adding a small number to a large number can result in loss of significance.




ok.  Maybe the wording should be a little clearer in the reference manual or an example given for the kinds of problems that can crop up due to the 32 bit double.

I can reduce one constant by 2451545 in the calculations and still get a usable result so maybe that's a better approach.  I'll give that a try.


As well as the significant digits issue be careful with doing any calculations that rely on the accuracy of the fractional part of a float (or double) because its internal representation as a binary fraction does not map exactly to the set of decimal fractions. Many common decimals are repeating binary fractions.

Go Up