具有整数的c加权平均值



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

但这似乎给了我错误的结果,我真的被实现卡住了。

有人有什么想法吗?


编辑

非常感谢您的快速回复,尽管我可能没有问清楚这个问题:我们有一个来自以前平均值和当前样本的所需权重因子。

如果你通过谷歌搜索找到了这个页面,并且正在寻找上面代码的更简单实现,那么你可能会喜欢这个。

此实现提供的配置选项较少,因为它只有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值被存储为乘以系数。通过这种方式,可以使用整数计算,而不会出现舍入错误,从而导致计算"陷入"错误值。检索输出值时,对整数值进行四舍五入并对该乘积进行补偿。

我认为这个实现更可读,但它的缺点是使用除法而不是移位。不过,如果系数是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;

相关内容

  • 没有找到相关文章

最新更新