整数的加权平均值

| 情况:我们有一个基于整数的微控制器,我们需要计算加权平均值(例如权重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;
但这似乎给了我错误的结果,而且我真的对实现感到困惑。 有人有想法吗? 编辑 非常感谢您的快速回复,尽管我可能还没有足够清楚地问过这个问题:我们需要根据先前的平均值和当前样本得出所需的权重。     
已邀请:
如果您通过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的幂,大多数编译器将足够聪明,可以使用位移。     
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
必须是足够大的数据类型。没有办法解决。     
如果要计算两组整数的加权平均值,则可以递增 在输入数据时记录每个系列的总和,并增加记录值的计数。 随着数据的输入,您可以将其添加到该系列的运行总计中。
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 );

}
    
好的,我们找到了解决方案,方法是根据需要调整值。
  #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;
    

要回复问题请先登录注册