difference between how a Microncontroller and a Microprocessor handle calculc

I designed a test station based on the Arduino Mega that records 3 temperatures, sun irradiance, wind speed and GPS. The collected data is post processed using data smoothing and then calculates power saving it all to a file on an SD drive. I also wrote an external C++ program that takes the same post processed data and filters out data that does not meet spec and also calculating power. The power calculated on the Arduino does not always match the power calculated by the external program and can be off by about 50% using the exact same temperature and irradiance data. I have done some manual calculations and found that they agree with the external program results. My question is , are the differences caused by the way the Arduino and a microprocessor handle calculations ?

Thanks

Justin Tabatchnick

You have two programs running on different platforms that should calculate the same result. You want the members of this forum to account for the difference without having access to the source of either program.

Are you doing the calculations with floating point numbers? Depending on the details of the calculation, the inherent inaccuracy in floating point numbers can be greatly amplified; could you be using a more accurate floating point representation on the external program? Are you getting integer-math'ed somewhere?

For anything beyond those really generic thoughts, you need to post the source of the two programs for us to look at.

Thanks for the reply . Basically the variables are declared as double in both programs and also power is calculated in the same way. For the most part there is correlation between results however they differ on a occasion by as much as 50% so , generally speaking, is there a difference between platforms in the way the calculation is done . The programs are large but I could try to condense it down if necessary.

Justin

see
https://www.arduino.cc/reference/en/language/variables/data-types/double/

which states
On the Uno and other ATMEGA based boards, this occupies 4 bytes. That is, the double implementation is exactly the same as the float, with no gain in precision.

a C++ program on a PC would probably use 8 bytes to store doubles

The BIG differences occur when very small values added(substr…) to/from large values.

Aware of this, you most often can alter code to minimize the effect

the main problem is when you are subtracting floating point numbers which differ in the final digits
when the result of the subtraction is normalised there is a rounding error

for example consider the Taylor series for the sine() function where one is adding and subtracting alternate terms
sine(x) = x - x^3/3! + x^5/5! - x^7/7! + …
This series is, in theory, valid for any finite angle. However, summing the series using the following program

/* test sin(x) function */

#include <stdio.h>
#include <math.h>

int main()
{
    double sinf(const double x);                  /* function prototype of sinf */
    double angles[]={.5f,1.0f,2.0f,5.0f,10.0f,15.0f,20.0f,25.0f,30.0f,50.0f};
    double x;                                               /* evaluate sin(x) */
    for(int i=0; i< 10; i++)
         printf("  sin(%2.1f) = %20.8f, library = %12.8f \n", angles[i], sinf(angles[i]), sin(angles[i]));
    return 0;
}

/*----------------------------------------------------------------------------*/
/* Function to evaluate sin(x) by summing the series (** is power):           */
/*  sin(x) = x - (x**3 / 3!) + (x**5 / 5!) - (x**7 / 7!) + ..                 */
double sinf(const double x)
{
    const double ACCURACY = 1.0e-8f;                      /* accuracy required */
    double xsq = x * x,                                           /* x squared */
          sin_x = x,                                  /* sum of sin(x) series */
          n = 3.0f,                           /* start iterations at 3rd term */
          term_n = x;                          /* value of nth term of series */
    //printf("              n                  term_n               sin_x\n");
    do
        {
        term_n = -(term_n * xsq / (n * (n - 1)));        /* evaluate nth term */
        sin_x = sin_x + term_n;                                  /* add term  */
        n = n + 2;                                                  /* next n */
        //printf(" sin(%5.1f) %3.0f %24f %20f\n", x, n, term_n, sin_x);
        }
    while (fabs(term_n) > ACCURACY);                            /* finished ? */
    return sin_x;                                       /* yes, return result */
}

a run using the gcc C compiler version 5.1.0 gives

  sin(0.5) =           0.47942552, library =   0.47942554
  sin(1.0) =           0.84147096, library =   0.84147098
  sin(2.0) =           0.90929741, library =   0.90929743
  sin(5.0) =          -0.95892441, library =  -0.95892427
  sin(10.0) =          -0.54420567, library =  -0.54402111
  sin(15.0) =           0.66512936, library =   0.65028784
  sin(20.0) =           1.52592909, library =   0.91294525
  sin(25.0) =          -5.36588192, library =  -0.13235175
  sin(30.0) =      -24048.72656250, library =  -0.98803162
  sin(50.0) = -8887603298304.00000000, library =  -0.26237485

if we change the floats to doubles

  sin(0.5) =           0.47942554, library =   0.47942554
  sin(1.0) =           0.84147098, library =   0.84147098
  sin(2.0) =           0.90929743, library =   0.90929743
  sin(5.0) =          -0.95892427, library =  -0.95892427
  sin(10.0) =          -0.54402111, library =  -0.54402111
  sin(15.0) =           0.65028784, library =   0.65028784
  sin(20.0) =           0.91294525, library =   0.91294525
  sin(25.0) =          -0.13235138, library =  -0.13235175
  sin(30.0) =          -0.98805326, library =  -0.98803162
  sin(50.0) =        9991.82828957, library =  -0.26237485

Process returned 0 (0x0)   execution time : 0.052 s
Press any key to continue.