Get the standard deviation of array

Is this correct ???

int  averageArray() {
  int total = 0;
   long total2 = 0;
  int average = 0;
   int average2 = 0;
  for (i = 0; i< numReadings; i++) {
    total = total + analogValues[i];
    
  }
  average = total/(numReadings);
  average2 = (total*total)/(numReadings);
  int std=sqrt(average2-(average*average));
  return std;
  

}

we can't see how you use your i index in the for loop... you will likely be impacted by integer being fairly "small" and truncing during division => consider using long and possibly casting to float or double (on a uno you don't get more precision) for your divisions

Please correct your post above and add code tags around your code:
[code]`` [color=blue]// your code is here[/color] ``[/code].

It should look like this:// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

No it isn't correct. You need the sum of the squares of the samples as well as the sum of the samples.
See, for example, the formula here which gives the "shortcut" formula for variance. Then square root it for the standard deviation.

Pete

You need to use floating point once you start to use division - integer division is not mathematically correct.

MarkT:
You need to use floating point once you start to use division - integer division is not mathematically correct.

floating point division won't be "mathematically correct" either.... but a bit more precise!

Good point - if 6 to 7 significant figures is enough, float will be OK.

el_supremo:
See, for example, the formula here which gives the "shortcut" formula for variance. Then square root it for the standard deviation.

Pete

Karma for refreshing my memory on standard deviation; God knows it needed that :slight_smile:

I just thew this together. I haven't actually uploaded to an arduino, but very briefly tested. It compiles in my arduino IDE though. This assumes the values you are taking the std dev are integers (most likely analogRead() values?). I don't know how big they are, so I've used longs. You should be able to modify accordingly. Let us know if it works!

/*
 * Get the mean from an array of ints
 */
float getMean(int * val, int arrayCount) {
  long total = 0;
  for (int i = 0; i < arrayCount; i++) {
    total = total + val[i];
  }
  float avg = total/(float)arrayCount;
  return avg;
}

/*
 * Get the standard deviation from an array of ints
 */
float getStdDev(int * val, int arrayCount) {
  float avg = getMean(val, arrayCount);
  long total = 0;
  for (int i = 0; i < arrayCount; i++) {
    total = total + (val[i] - avg) * (val[i] - avg);
  }

  float variance = total/(float)arrayCount;
  float stdDev = sqrt(variance);
  return stdDev;
}

void setup() {
  // example test
  Serial.begin(9600);
  while(!Serial){;}

  // test array
  int * arr = new int[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  
  int arrayCount = 10; // number of elements

  float mean = getMean(arr, arrayCount);
  float std = getStdDev(arr, arrayCount);

  // print the output
  Serial.print("Mean: ");
  Serial.println(mean);
  Serial.print("Standard deviation: ");
  Serial.println(std);
}

void loop() {
  // put your main code here, to run repeatedly:

}

@sterretje: Thanks :slight_smile:

Pete

If you implement the computation using the "shortcut" method, you don't need to store the values in an array first. It can all be done "on-the-fly".

Pete

el_supremo:
If you implement the computation using the "shortcut" method, you don't need to store the values in an array first. It can all be done "on-the-fly".

Pete

Yep, I just took a look at the link. Seems a better way to go! Also the advantage of calculating a running standard deviation, if need be...

On this note, I'm fairly sure there is an algorithm for calculating a running mean? Anyone know the name? For the life of me can't remember it (I think it begins with a W??).

You really don't need an algorithm for calculating a running mean. If the current sum of the samples is S and there are N of them, then the next mean is (S+new_sample)/(N+1).

Pete

Silly me. Sorry, it was actually real time standard deviation I was thinking of. It's this algorithm that I was thinking of: Algorithms for calculating variance - Wikipedia

It's called Welford algorithm, and is most likely overkill in most cases. Still, good to know!

Thanks. I had never run across Welford's algorithm. That is a neat way of doing a running SD which removes the problem of having the sum of squares increasing without bound. The "shortcut" method (above) will start to run into problems after a minimum of about 4100 samples (assuming that the sum of squares is kept in a 32-bit integer). I wouldn't expect that there would be many Arduino projects that needed the SD calculated over so many samples but it's useful to know there's an efficient way to do it.

Pete