移動平均のプログラム(ダサっ)
#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 ; }
でも、このプログラムは、以下の点で問題がある。
- 範囲のデータを加算しているけど、加算の繰り返しが多い。
- 配列にデータを最初に全て読み込んでいるけど、長時間のデータならば大量のメモリが必要。
- 測定しながら移動平均を計算する場合、データはどうする?
移動平均のプログラム(ちょっと改良)
全部のデータを覚えるのはメモリの無駄なので、移動平均する直近のデータだけを覚えるように改良する。
しかし、データを保存する度に、配列をずらす処理も無駄なので、データを保存する場所(以下の例では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 ; }