-4

I have an array of samples, suppose its length is 10. Now I want to weight them, so that I can get an average where the oldest samples take a little bit more weight than the fresh ones.

For example, Position 1 = 100%, Position 10 = 10% weighing.

How is this called, and how do I write such a function correctly?

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
Maestro
  • 9,046
  • 15
  • 83
  • 116
  • 1
    This is called a [weighted average](http://en.wikipedia.org/wiki/Weighted_arithmetic_mean). The algorithm for calculation is also in that link. – wolfPack88 Mar 19 '15 at 15:46
  • 4
    I'm voting to close this question as off-topic because it's a maths question – thelaws Mar 19 '15 at 15:47
  • It is also a duplicate: http://stackoverflow.com/questions/9915653/how-to-calculate-iteratively-the-running-weighted-average-so-that-last-values-to – chmike Mar 19 '15 at 15:48
  • @thelaws Its not a math question? Im just looking for an implementation in C – Maestro Mar 19 '15 at 15:59
  • @wolfPack88 There is no code in that link. I can show you the wikipedia page for AES, but you still would have no clue how to implement that. – Maestro Mar 19 '15 at 16:01
  • 2
    You asked how to do something, I provided an algorithm. SO is not a "write code for you" service, and having built up 2k in rep, you should now that by now. – wolfPack88 Mar 19 '15 at 16:02
  • ..."know that by now", not "now that by now". – wolfPack88 Mar 19 '15 at 16:10
  • @wolfPack88 Since this such a common task, I dont expect anyone to write code for me, there must a lot of existing (and well-tested/optimized) implementations out there. – Maestro Mar 19 '15 at 16:56
  • If you have a fixed set of weights you want to apply to a vector of samples, then why can't you simply do the math iteratively? – jschultz410 Mar 19 '15 at 17:20
  • In which case you are asking for an offsite resource, which is also off-topic here. – wolfPack88 Mar 19 '15 at 17:33

2 Answers2

2

This might not be exactly for what you are asking, but exponential moving average (EMA) is usually written something like this:

double exp_avg(double avg, double sample, double sample_weight)
{
    return sample * sample_weight + avg * (1 - sample_weight);
    // return avg + (sample - avg) * sample_weight;  // equivalent alternative
}

When first establishing an EMA, the average should be set equal to the first sample.

jschultz410
  • 2,849
  • 14
  • 22
0

Here's a simplistic implementation of what you asking.

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

int normalize_weights(double *weights, size_t num_weights)
{
  double sum = 0;

  for (size_t i = 0; i < num_weights; ++i)
  {
    if (weights[i] < 0)
      return -1;

    sum += weights[i];
  }

  if (sum == 0)
    return -1;

  for (size_t i = 0; i < num_weights; ++i)
    weights[i] /= sum;

  return 0;
}

int weighted_avg(double *avg_ptr, const double *samples, size_t num_samples, const double *weights, size_t num_weights)
{
  if (num_samples != num_weights)
    return -1;

  double avg = 0;

  for (size_t i = 0; i < num_weights; ++i)
    avg += samples[i] * weights[i];

  *avg_ptr = avg;

  return 0;
}

int main(int argc, char **argv)
{
  double weights[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; 
  double samples[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  double avg;

  if (normalize_weights(weights, sizeof(weights) / sizeof(weights[0])))
    abort();

  for (size_t i = 0; i < sizeof(weights) / sizeof(weights[0]); ++i)
    printf("Normalized weight[%u] = %lf\n", (unsigned) i, weights[i]);

  if (weighted_avg(&avg, samples, sizeof(samples) / sizeof(samples[0]), weights, sizeof(weights) / sizeof(weights[0])))
    abort();

  printf("\nWeighted average is %lf\n", avg);

  return 0;
}
jschultz410
  • 2,849
  • 14
  • 22