1

情况:我们有一个基于整数的微控制器,我们需要计算加权平均值(例如,权重 32,如 31-1),并将其存储在数组中。

最终代码将在 C 中。

(并且可以肯定的是,这不是家庭作业:))

我们正在考虑将模除法的结果与结果的权重(平均计算)一起存储,并在下一轮用作附加数据。

如果我们有浮动,它会是这样的:

avg[i] = ( avg[i-1] * (WEIGHT-1) + measured ) / WEIGHT;

既然我们没有,我在想:

pt = (mod == 0) ? WEIGHT-1 : WEIGHT-2;
tmp = avg[i-1] * pt + mod + measured;
avg[i] = tmp / WEIGHT;
mod = tmp % WEIGHT;

但这似乎给了我错误的结果,我真的坚持实施。

任何人,有一些想法?


编辑

非常感谢您的快速回复,尽管我可能没有问得足够清楚:我们从以前的平均值和当前样本中获得了所需权重的一个因素。

4

4 回答 4

4

如果您通过谷歌搜索进入此页面并正在寻找上述代码的更简单实现,那么您可能会喜欢这个。

此实现提供较少的配置选项,因为它只有 1 个定义。在您的特定情况下,这可能是一个优点或缺点。

#define COEFFICIENT 32

static int sample_weighted = 0;
int output = 0;

sample_weighted *= COEFFICIENT - 1;
sample_weighted += raw_value * COEFFICIENT;
sample_weighted /= COEFFICIENT;

output = (sample_weighted + (COEFFICIENT/2) - 1) / COEFFICIENT;

与常规加权过滤器的区别在于 sample_weighted 值乘以 COEFFICIENT 存储。这种方式可以使用整数计算而不会导致计算“卡”在错误值上的舍入错误。检索输出值时,整数值会被舍入并针对此乘法进行补偿。

我认为这个实现更具可读性,但它确实有一个缺点,它使用除法而不是位移。不过,只要 COEFFICIENT 是 2 的幂,大多数编译器都会足够聪明地使用位移。

于 2012-11-28T22:41:35.660 回答
0

好的,我们找到了解决方案,通过改变我们需要的值。

  #define TOTAL_WEIGHT 128
  #define SAMPLE_WEIGHT 24
  #define SHIFT 8
  #define SHIFT_VAL 256
  #define SHIFT_WEIGHT 7

  static int sample_weighted = 0;
  int output = 0;
  int sample_tmp = 0U;

    sample_tmp = sample_tmp << SHIFT;
    sample_tmp = sample_tmp * SAMPLE_WEIGHT;
    sample_weighted = sample_weighted * ( TOTAL_WEIGHT - SAMPLE_WEIGHT );
    sample_weighted = sample_weighted + sample_tmp;
    sample_weighted = sample_weighted >> SHIFT_WEIGHT;
    output  = (sample_weighted + (SHIFT_VAL/2) -1 ) >> SHIFT;
于 2011-05-02T11:25:38.207 回答
0

如果您想计算两组整数的加权平均值,您可以在数据进入时增量记录每个系列的总和并增加记录值的计数。

随着数据的传入,您将其添加到该系列的运行总数中。

int weighted_mean( int count_a, int sum_a, int count_b, int sum_b ){
  return = ((count_a * sum_a) + ( count_b * sum_b )) / ( sum_a + sum_b );
}

void recv_data( int a, int b )
{
  global_sum_a += a;
  global_count_a++;

  global_sum_b += b;
  global_count_b++;

  int weighted_mean_so_far = weighted_mean( global_count_a, global_sum_a, global_count_b, global_sub_b );

}
于 2011-04-13T08:09:25.223 回答
0
for (i = 0; i < num_elements; i++)
{
    sum_data += data[i] * weight[i];
    sum_weights += weight[i];
    average[i] = sum_data / sum_weights;
}

显然,sum_data必须是足够大的数据类型;没有办法解决这个问题。

于 2011-04-13T07:54:01.017 回答