加权均值与整数

时间:2011-04-13 06:51:37

标签: c integer mean

情况:我们有一个基于整数的微控制器,我们需要计算加权平均值(例如,权重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 个答案:

答案 0 :(得分:4)

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

此实现提供的配置选项较少,因为它只有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的幂,大多数编译器都会足够聪明地使用位移。

答案 1 :(得分: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必须是足够大的数据类型;没有办法解决这个问题。

答案 2 :(得分: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 );

}

答案 3 :(得分: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;