1

状況:整数ベースのマイクロコントローラがあり、加重平均(たとえば、31-1のような重み32)を計算し、それを配列に格納する必要があります。

最終的なコードは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

4 に答える 4

4

あなたがグーグル検索でこのページに行き、上記のコードのより簡単な実装を探しているなら、あなたはこれが好きかもしれません。

この実装では、定義が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の累乗であれば、ほとんどのコンパイラはビットシフトを使用するのに十分スマートです。

于 2012-11-28T22:41:35.660 に答える
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十分な大きさのデータ型である必要があります。それを回避する方法はありません。

于 2011-04-13T07:54:01.017 に答える
0

2セットの整数の加重平均を計算する場合は、データが入ってくるときに各系列の合計を増分的に記録し、記録された値のカウントを増分することができます。

データが入ってくると、そのシリーズの現在の合計に追加します。

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 );

}
于 2011-04-13T08:09:25.223 に答える
0

OK、ニーズに合わせて値をシフトすることで、解決策を見つけました。

  #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;
于 2011-05-02T11:25:38.207 に答える