如何计算衰减平均值?

时间:2015-03-19 15:45:05

标签: c average c99 weighted-average

我有一个样本数组,假设它的长度为10。 现在我想对它们进行加权,这样我就可以得到一个平均值,其中最旧的样本比新鲜样本的重量略高一些。

例如,位置1 = 100%,位置10 = 10%称重。

如何调用,以及如何正确编写这样的函数?

2 个答案:

答案 0 :(得分:0)

这可能不完全符合您的要求,但exponential moving average (EMA)通常是这样写的:

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
}

首次建立EMA时,应将平均值设置为等于第一个样本。

答案 1 :(得分:0)

这里是你所要求的简单实现。

#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;
}