Go Down

### Topic: OVF (stack overflow) when calculating a 5th order polynomial on an UNO (Read 17649 times)previous topic - next topic

#### MichaelMeissner

#15
##### Mar 17, 2013, 03:31 pm
Well, if you are doing polynomial calculations on the Uno, note that the all of the AVR processors map 'double' into 'float', which means reduced precision and exponent range.  Arm based processors like Due or a Teensy 3.0 use the same format for double as x86's.

Another note, if you are doing lots of floating point calculations, both the AVR and Due/Teensy 3.0 based processors do not have floating point hardware, and emulate the floating point.  If you are doing lots of floating point calculations, perhaps you would do better to get something like a Raspberry Pi/Beagle Board/maybe pcDunio which has hardware floating point to do the calculations.  Since these machines run Linux varients, they also have much more memory to work with.  But the programming of these is different from the Arduino, and you have less pins for controlling hardware.  If you are controlling devices, perhaps a combination, where you use the R-PI to do the brain work, and a controller to talk to hardware.

#### robtillaart

#16
##### Mar 17, 2013, 05:53 pm
Interesting to see some of my code back

Some Arduino floating points points:
- the Arduino has only 7 digits of precision, the compiler will take care of rounding
- the compiler accepts E notation in float constants, which removes unneeded pow(10, n) from your code
- a fifth order polynome with integer powers can speed up by a big factor by decomposing it using only 5 multiplies and 5 additions.

Code: [Select]
`void setup(){  Serial.begin(9600);  Serial.println("start...");    long val = 420;  f = 1.354026784*pow(10,-8)*pow(val,5) //pow(10,-8) raises 1.354026784 to the 10-8               - 2.559722383*pow(10,-5)*pow(val,4)                + 0.0192917182*pow(val,3)                - 7.24448384*pow(val,2)                + 1356.112407*val                - 101259.7822;                 Serial.println(f,5);  Serial.println(float2s(f, 5));  // removing pow() completely  f = 1.354026784E-8* val*val*val*val*val - 2.559722383E-5* val*val*val*val + 1.92917182E-2 * val*val*val - 7.24448384 * val*val + 1356.112407*val - 101259.7822;  Serial.println(f,5);  Serial.println(float2s(f,5));    // minimize math   f = (((( 1.354026784E-8 * val - 2.559722383E-5 ) * val + 1.92917182E-2 ) * val - 7.24448384 ) * val + 1356.112407) * val - 101259.7822;  Serial.println(f,5);  Serial.println(float2s(f, 5));}void loop(){}`

Quote
116.9063

output
start...
116.90625
1.16906 E+2

116.84375
1.16843 E+2

116.79688
1.16796 E+2

Note that method 2 and 3 which uses less operations already differ in the 4th digit, so calculating this with more than 5 digits is speculative at best.

This is caused by the fact that all the partial sums  ( a.pow(b,n) ) are in the same order of magnitude 10^5..10^6 and their sum is 2 to 3 orders of magnitude lower.
(you're losing significant bits here)

BTW according to Excel the "right" value == 116.935898400974 so simplifying the math does make it worse this time.

Excel snippet (,'s are due to localization)
Code: [Select]
`coefficient             420^n                   partial result1,354026784000000E-08 1,306912320000000E+13 1,769594285619580E+05-2,559722383000000E-05 3,111696000000000E+10 -7,965077900291570E+051,929171820000000E-02 7,408800000000000E+07 1,429284818001600E+06-7,244483840000000E+00 1,764000000000000E+05 -1,277926949376000E+061,356112407000000E+03 4,200000000000000E+02 5,695672109400000E+05-1,012597822000000E+05 1,000000000000000E+00 -1,012597822000000E+05                            sum = 1,169358984009740E+02`

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up