Project_OKI’s diary

エンジニアの勉強ブログ

C言語基礎知識51(加算平均と単純移動平均)

 

1.目的

  • 加算平均と単純移動平均の違いについて記載する。
  • それぞれのC言語での書き方について記載する。

 

参照:https://chatgpt.com/share/678af057-0a98-8013-9476-12d36afa75c1

 

目次

 

2.単純移動平均とは

直近の n 個のデータの重み付けのない単純な平均
・例えば、10日間の終値単純移動平均とは、直近の10日間の終値の平均である。
 
 

2.加算平均とは

・複数の数値を足してその個数で割る平均値のことを指す。
 
 

3.プログラムの作成(移動平均)

#include <stdio.h>

/* ********************
* 移動平均計算
* @param arr    : データ
* @param n      : データ数
* @param period : 計算する期間
* @return  void : None
********************** */
void calculate_sma(int arr[], int n, int period) {
    double sum;
    double average;
    
    if (n < period) {                               ///<データ数確認
        printf("データ数が移動平均の期間より少ないです。\n");
        return;
    }
    
    ///データ数有り
    printf("データ数:%d,期間:%d\n",n,period);
    ///データ数 - 期間 + 1 分ループ
    for (int i = 0; i <= n - period; i++) {
        sum = 0;
        //期間分ループ (対象期間の合計値算出)
        for (int j = i; j < i + period; j++) {
            sum += arr[j];                          ///<合計値算出
        }
        if(period != 0){                            ///<0除算防止
            average = sum / period;                   ///<期間の平均値算出
        }
        printf("期間 [%d - %d] の単純移動平均: %.2f\n", i + 1, i + period, average);
    }
}

int main() {
    int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 15,20};
    int size = sizeof(data) / sizeof(data[0]);
    int period = 3;                                 ///< 移動平均の期間
    calculate_sma(data, size, period);
    return 0;
}

結果:https://paiza.io/projects/ZUS70Q9QOywA5O7uxAPz5A?language=c

 

3.プログラム作成(加算平均)

#include <stdio.h>

//加算平均算出関数
double calculate_sum_average(int arr[], int n) {
    double ave = 0.0; ///<平均値
    int sum = 0;///<合計値
    
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
    if(n != 0){
        ave = sum / n;
    }
    return ave;
}

int main() {
    int data[] = {1, 2, 3, 4, 5};
    int size = sizeof(data) / sizeof(data[0]);  ///データ数の算出
    
    ///平均値の算出
    double average = calculate_sum_average(data, size);
    printf("加算平均: %.2f\n", average);
    return 0;
}

結果:https://paiza.io/projects/NkfxP1O4ciY2bMermfirgA

 

5.プログラムの作成(移動平均2)

3.移動平均のプログラムでは、全てのデータが事前に分かっていて、データ数が分かっている場合しか計算出来ない。

組み込みの場合、AD変換などを割り込みで、発生させ、定期的に移動平均を算出したい場合がある。

その場合の移動平均処理を記載する。

#include <stdio.h>
#define BUF_SIZE 3

///移動平均用構造体
typedef struct{
    int bufnum;
    int buf[BUF_SIZE];
}Add_Ave;

/* ********************
* バッファシフト用関数
* @param data:バッファに格納するデータ
* @param pAdd_Ave:移動平均用構造体
* @return  void : None
********************** */
void ShiftBuf(int data,Add_Ave *pAdd_Ave) {
    if(pAdd_Ave == NULL){
        return;
    }
    pAdd_Ave->bufnum++;///データ数更新
    ///バッファ最大値確認
     pAdd_Ave->bufnum = (pAdd_Ave->bufnum>BUF_SIZE)?BUF_SIZE:pAdd_Ave->bufnum;
     
    // バッファをシフトして最新のデータを挿入
    for (int i = 0; i < BUF_SIZE - 1; i++) {
//        printf("i:%d,%d\n",i,pAdd_Ave->buf[i + 1]);
         pAdd_Ave->buf[i] =  pAdd_Ave->buf[i + 1];
    }
    pAdd_Ave->buf[BUF_SIZE - 1] = data;  //一番最後にデータを入れる。
}

//加算平均算出関数
double Calc_AddAve(Add_Ave *pAdd_Ave) {
    double ave = 0.0; ///<平均値
    int sum = 0;///<合計値

    if(pAdd_Ave->bufnum <BUF_SIZE){///計算に必要なデータ数確認より小さい時
        return (double)pAdd_Ave->buf[pAdd_Ave->bufnum];///新しいデータをそのまま返す。
    }

    ///合計値算出
    for (int i = 0; i < pAdd_Ave->bufnum; i++) {
        sum += pAdd_Ave->buf[i];
    }
    ave = (double)sum / pAdd_Ave->bufnum;
    return ave;
}

int main() {
    //計算用構造体の初期化
    Add_Ave g_Add_Ave = {
        0,
        {0}
    };
    
    ///用意したデータ
    int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 15,20};
    int size = sizeof(data) / sizeof(data[0]);  ///データ数の算出

    ///平均値の算出
    for(int i=0;i<size;i++){
        printf("--入力値:%d--\n",data[i]);
        
        //計算バッファへの格納
        ShiftBuf(data[i],&g_Add_Ave);///<計算バッファ更新
        
        for (int i = 0; i < BUF_SIZE; i++) {///バッファに格納されている数値確認
            printf("buf:%d\n",g_Add_Ave.buf[i]);
        }
        
        double average = Calc_AddAve(&g_Add_Ave);///平均値の計算
        printf("加算平均: %.2f\n", average);
    }
    return 0;
}

実行結果:https://paiza.io/projects/iTPougLsJ53x4Mfw2DQzww

 

 

組み込みC言語