如何解决整数的加权平均值
| 情况:我们有一个基于整数的微控制器,我们需要计算加权平均值(例如权重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;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。