RustにいればRustに従え(3) 移動平均をmut無、for無で計算。表示にfor使用

Joseph Halfmoon

過去2回、アカラサマなmut宣言とfor文なしに計算を続けてきましたが、今回とうとうfor文を使ってしまいました。だって結果の表示部分だからお楽にしたかったんだ。まあ計算本体は、吉例にもとづきmut無、for無っす。それがどれほどの意味があるのか知らんけど。まあ縛りをかけた方がRustらしくなるかと?ホントか?

※『RustにいればRustに従え』関係記事 index はこちら

※動作確認は、Windows11のWSL2上にインストールしたUbuntu20.04LTS上のrustc 1.64.0 (a55dd71d5 2022-09-19) で行っています。

たかが移動平均、されど移動平均

移動平均、今回計算してみたものと同じデータを表計算ソフトで計算したものを冒頭のアイキャッチ画像にかかげました。表計算ソフトを使えば一撃。なんでそんなものをあくせく(アクセスではないっす)計算しないとならないのよ。

でもね、「計算構造」的には移動平均も、FIRフィルタも、コンボルーション演算も皆同じだ、と(乱暴だな、自分。)移動平均が計算できるのならそいつらは皆以下同文でやっつけられる筈だ、と。ホントか?

まあ、とりあえず短いデータで移動平均やってみたです。

Rustで書いてみたコード

せっかくなのでVScode画面のキャプチャです。MovingAverage

計算部分は、ずっとlet、letとmut無の代入文ばかりで計算できているのに、最後、結果を印字するところでfor使っちまってます。だって楽なんだもん。というか、イテレータとクロージャの闇に疲れちまったデス。

いちおうテキスト形式のソースが以下に。

fn main() {
    let testdat: [f64; 10] = [1.5, 2.7, 2.5, 3.3, 3.1, 4.1, 4.1, 5.1, 5.9, 6.6];
    let datlen: usize = testdat.len();
    let avgspn: usize = 5;
    let dlis: Vec<usize> = (0..datlen - avgspn + 1).collect();
    let result = dlis.iter().map(|i| {
        let lis: Vec<usize> = (0..avgspn).collect();
        lis.iter().fold(0.0, |acc, x| 
            match testdat.get(i+x) {
                Some(fv) => acc + fv,
                None => acc,
            }) / avgspn as f64 }
        );
    println!("Moving average(5)");
    println!("INPUT: {:?}", testdat);
    println!("OUTPUT:");
    for item in result {
        print!("{0:3.2} ", item);
    }
    println!();
}
実行結果

実行結果が以下に。表計算で一撃の結果を得るのに何時間かかったんだ?movingAVGresult

やっぱC頭の年寄にはRustはムツカシすぎる?

RustにいればRustに従え(3) CRC8をmut無、for無で計算する へ戻る

RustにいればRustに従え(4) フィルタ実験用のサンプル波形生成、mut無、for最小 へ進む