Highslide for Wordpress Plugin

按照維基百科上面的定義,簡單移動平均是某變數之前n個數值的未作加權算術平均,方程式為:

SMA = { p_1 + p_2 + \cdots + p_n \over n }

當計算連續的數值,一個新的數值加入,同時一個舊數值剔出,所以無需每次都重新逐個數值加起來:

SMA_{t1} = SMA_{t0} - {p_1 \over n} + {p_{n+1} \over n}

 

那麼如果今天因為程式記憶體有限,無法做到無窮數列這樣一直命名變數,而是必須在限定數列的陣列長度為n的情況下,計算n點移動平均,該怎麼做呢?

我室友之前曾經有給我看過他接手學長的資料,裡面學長是如下面「void case1」中的,利用同一個陣列存取資料的時間差(這輪迴圈對第 i 個重新給值,但是第 i+1 個還是上一輪給的舊資料),去計算移動平均。當初一開始乍看覺得沒問題,甚至還覺得他這樣的思路很神奇。

但是今天室友說他在檢查的時候,發現用一樣的邏輯,但是給予值 {0,1,2,3,4}去循環就發現出錯了,幾經測試終於發現問題在於,因為只用了一個數列,所以在計算時它是會多跳一個,變成 SMA  =  SMA_Previous – a_Pre_round[i+1] – a[i] ,這樣就只有算到 n-1 個點的移動平均。

想了半天,最後覺得最快的解決方式還是另外再命名一個數列a_pre,已經加總過的 a 在寫入新資料之前,會先存到 a_pre ,供下一次使用,成果如「 void case2」所示,這下終於正常了。

   1: #include <stdio.h>

   2: #include <math.h>

   3: #define n 5    //五點移動平均

   4: /* edited by Kermit  20131025*/

   5: void case1(int number[10]);     //原本的寫法(發現實際會變成 n-1 點 SMA) 

   6: void case2(int number[10]);     //改寫過的SMA,利用兩個數列存資料 

   7: int main()

   8: {

   9:      

  10:     int number[10]={0,1,2,3,4,0,1,2,3,4};//number[10]要先給值不能未給值就呼叫計算,模擬數列的值 

  11:     case1(number);

  12:     printf("---------------------------------------------\n");

  13:     case2(number);

  14:     system("pause");

  15:     return 0;

  16: }

  17: void case1(int number[10])

  18: {

  19:     int sum=0;

  20:     int i, count=0, count_max=n,a[n]={0};

  21:     for(i=0; i<10; i++)

  22:     {

  23:         a[count]=number[i];

  24:         printf("i=%d\t sum=pre_sum:%d\t -a[%d]:%d\t +a[%d]:%d\t=",i,sum,(count+1)%count_max,a[(count+1)%count_max],count,a[count]);

  25:         sum=sum-a[(count+1)%count_max]+a[count];

  26:         printf("%d\n",sum);

  27:         if(count==count_max-1){count=0;}

  28:         else{count++;}

  29:     }        

  30: }

  31: void case2(int number[10])

  32: {

  33:     int sum=0;

  34:     int i, count=0, count_max=n,a[n]={0},a_pre[n]={0};

  35:     for(i=0; i<10; i++)

  36:     {

  37:         a[count]=number[i];

  38:         printf("i=%d\t sum=pre_sum:%d\t -a_pre[%d]:%d\t +a[%d]:%d\t=",i,sum,count,a_pre[count],count,a[count]);

  39:         sum=sum-a_pre[count]+a[count];

  40:         printf("%d\n",sum);

  41:         a_pre[count]=a[count];

  42:         if(count==count_max-1){count=0;}

  43:         else{count++;}

  44:     }        

  45: }

Related Posts with Thumbnails
有1個迴響於 “[C語言練習]利用循環變數計算移動平均”
  1. 室友 說道:

    今天重看文章會心一笑XDDD

  2.  
留下迴響