情况:我们有一个基于整数的微控制器,我们需要计算加权平均值(例如,权重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;
但这似乎给了我错误的结果,而且我真的坚持实施。
任何人,有一些想法吗?
非常感谢您的快速反应,尽管我可能没有明确地提出这个问题:我们从之前的平均值和当前样本中得到了所需权重的因子。
答案 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;