ホーム » スタッフ » 斉藤徹 » 講義録 » 情報制御基礎 » 移動平均のプログラム

2018年6月
« 5月    
 12
3456789
10111213141516
17181920212223
24252627282930

最近の投稿(電子情報)

アーカイブ

カテゴリー

移動平均のプログラム

移動平均のプログラム(ダサっ)

#include <stdio.h>
#define WIDTH 5
double xt[1000] ; // 元波形データ
double yt[1000] ; // 移動平均処理後のデータ
int main() {
    int    i ; 
    double t , x ;
    // 全データを読み込む(入力はコンマ区切りの2データ)
    for( i = 0 ; scanf( "%lf,%lf" , &t , &x ) == 2 ; i++ )
        xt[ i ] = x ;
    // データ xt[*] の移動平均を yt[*] に求める。
    for( i = WIDTH ; i < 1000 - WIDTH ; i++ ) {
        int j ;
        double s = 0.0 ; // 合計
        // 前後の値の合計を求める
        for( j = -WIDTH ; j <= WIDTH ; j++ )
            s = s + xt[ i + j ] ;
        // 合計をデータ数で割る
        yt[ i ] = s / (WIDTH * 2 + 1) ;
    }
    // 処理結果を出力する。
    for( i = 0 ; i < 1000 ; i++ )
        printf( "%d,%lf,%lf\n" , i , xt[i] , yt[i] ) ;
    return 0 ;
}

でも、このプログラムは、以下の点で問題がある。

  1. 範囲のデータを加算しているけど、加算の繰り返しが多い。
  2. 配列にデータを最初に全て読み込んでいるけど、長時間のデータならば大量のメモリが必要。
  3. 測定しながら移動平均を計算する場合、データはどうする?

移動平均のプログラム(ちょっと改良)

全部のデータを覚えるのはメモリの無駄なので、移動平均する直近のデータだけを覚えるように改良する。
しかし、データを保存する度に、配列をずらす処理も無駄なので、データを保存する場所(以下の例ではbp)を保存したら次の場所を示すように記述してみる。

#include <stdio.h>

#define WIDTH 10
double buff[ WIDTH ] ; // 直近のWIDTH個だけ保存
int    bp = 0 ;        // 最新データの場所
double bs = 0.0 ;      // 直近のWIDTH個の合計

int main() {
    int i ;
    double t , x ;
    for( i = 0 ; scanf( "%lf,%lf" , &t , &x ) == 2 ; i++ ) {
        // WIDTH個前のデータを捨てるために合計から引く
        bs = bs - buff[ bp ] ;

        buff[ bp ] = x ;      // 最新データを保存
        bs = bs + x ;         // 最新のデータで合計
        // 直近のデータを覚える場所を移動
        bp++ ;
        if ( bp >= WIDTH )
            bp = 0 ;
        // 移動平均を出力
        printf( "%d %lf\n" , i , bs / WIDTH ) ;
    }
    return 0 ;
}