簡體   English   中英

計算 c 中 static 數組的移動平均值

[英]calculate moving average of an static array in c

我編寫了這段代碼來計算 c 中數組的移動平均值。

Array_MovingAverage(const int inputSeries[], 
                    size_t inputSize, 
                    size_t window, 
                    float output[],
                    size_t outputSize) {
  if (inputSeries && output != NULL){
    for(size_t i = 0; i < window ; i++)
      if (window < inputSize)
        if (inputSeries != NULL && output != NULL) {
          if(outputSize >= inputSize) {
            size_t inputSize[11] =  {1, 2, 2, 3, 6, 8, 9, 2, 1, 2, 1};
            const uint8_t window = 5;
            {
              const int inputSeries[] = {1, 2, 2, 3, 6, 8, 9, 2, 1, 2,1};

              double window = 5;
              double c = 2.0;
              double d = 2.0;

              for(int i = 0; i < window; i++)
              {
                c += inputSeries[i];
                d = c / window;
              }

              return true;
            }
          }
        }
    }
  }

我一直在嘗試計算 C 中數組的移動平均值並獲得所需的 output 但它似乎不起作用。 您能否給我一個建議,如何計算 C 中 static 數組的移動平均值?

Output 應該是:

Moving Average: 1 2 2 3 6 8 9 2 1 2 1
                0 0 0 0 3 4 6 6 5 4 3

讓我們從頭開始。 您嘗試修改此代碼只會使您非常不清楚您要做什么,並且原始代碼在任何情況下似乎都有缺陷。 處理代碼的問題可能是徒勞的。

首先,對於移動平均值 N,您保留最后 N 個值的總和,對於每個新樣本,您:

  1. 將樣本 [n] 添加到總和
  2. 從 sum 中減去 sample[nN]
  3. output 總和/N

采用您的接口,但省略了冗余的outputSize - output 與輸入的大小相同),實現可能如下所示:

void Array_MovingAverage( const int* inputSeries, 
                          size_t inputSize, 
                          size_t window, 
                          float* output ) 
{
    int sum = 0 ;

    if( inputSeries != NULL && output != 0 )
    {
        for( size_t i = 0; i < inputSize; i++ )
        {
            // Add newest sample
            sum += inputSeries[i] ;
            
            // Subtract oldest sample
            if( i >= window )
            {
                sum -= inputSeries[i - window] ;
            }
            
            output[i] = (float)sum / window ;
        }
    }
}

要使用它,您可能有:

int main()
{
    const int input[] = {1, 2, 2, 3, 6, 8, 9, 2, 1, 2, 1};
    const size_t size = sizeof(input) / sizeof(*input) ;
    float output[size] ;
    
    Array_MovingAverage( input, size, 5, output ) ;
    
    for( size_t i = 0; i < size; i++ )
    {
        printf( "%.2f\n", output[i]) ;
    }

    return 0;
}

對於您的樣本數據{1, 2, 2, 3, 6, 8, 9, 2, 1, 2, 1} ,output 是:

{0.20, 0.60, 1.00, 1.60, 2.80, 4.20, 5.60, 5.60, 5.20, 4.40, 3.00}

在此處輸入圖像描述

現在您的問題尚不清楚,但形成其他評論似乎您希望破解此 function 以忽略調用者提供的輸入,因為您無法修改調用者。 坦率地說,這很奇怪,但這是一種“安全”的方式。 讓我們假設outputSize將被恢復,因為顯然您需要它來避免調用者 output 緩沖區溢出。 最簡單的解決方案是將 function 的整個主體包裹起來,這是一個附加的 shell 大括號 {...} 允許您創建覆蓋輸入參數的陰影變量,而不會觸及代碼的 Z65E8800B5C6800AAD896F8AFCZ2:

void Array_MovingAverage( const int* inputSeries, 
                          size_t inputSize, 
                          size_t window, 
                          float* output,
                          size_t outputSize ) 
{
    // Prevent unused warnings
    (void)inputSeries ;
    (void)inputSize ;
    (void)window ;

    // Create block to allow variables to be "shadowed"
    {
        // Override inputs
        // NASTY HACK
        const size_t inputSize = 11 ;
        const int inputSeries[11] = {1, 2, 2, 3, 6, 8, 9, 2, 1, 2, 1};
        const size_t window = 5 ;
        
        int sum = 0 ;
    
        if( inputSeries != NULL && output != 0 )
        {
            for( size_t i = 0; i < inputSize; i++ )
            {
                // Add newest sample
                sum += inputSeries[i] ;
                
                // Subtract oldest sample
                if( i >= window )
                {
                    sum -= inputSeries[i - window] ;
                }
                
                // Only write to caller output if index in bounds
                if( i < outputSize )
                {
                    output[i] = (float)sum / window ;
                }
            }
        }
    }
}

當然,您可以簡單地更改變量名稱並忽略輸入參數,但如果在任何復雜的現有工作代碼中執行此操作,上述 hack 可能不太容易出錯(不重命名變量)。 也就是說,這樣的解決方案可能如下所示:

void Array_MovingAverage( const int* inputSeries, 
                          size_t inputSize, 
                          size_t window, 
                          float* output,
                          size_t outputSize ) 
{
    // Prevent unused warnings
    (void)inputSeries ;
    (void)inputSize ;
    (void)window ;

    // Local "input" data
    const int input[] = {1, 2, 2, 3, 6, 8, 9, 2, 1, 2, 1};
    const size_t size = sizeof(input) / sizeof(*input) ;
    const size_t width = 5 ;
 
    int sum = 0 ;

    if( input != NULL && output != 0 )
    {
        for( size_t i = 0; i < size; i++ )
        {
            // Add newest sample
            sum += input[i] ;
            
            // Subtract oldest sample
            if( i >= window )
            {
                sum -= input[i - width] ;
            }
            
            // Only write to caller output if index in bounds
            if( i < outputSize )
            {
                output[i] = (float)sum / window ;
            }
        }
    }
}

您的代碼中有很多問題:

Array_MovingAverage(const int inputSeries[], size_t inputSize, size_t window, float output[],
                        size_t outputSize) {
 if (inputSeries && output != NULL){
   for(size_t i = 0; i < window ; i++)
     if (window < inputSize)
       if (inputSeries != NULL && output != NULL) {  << This is same as if statemend 3 lines above
         if(outputSize >= inputSize) {
           size_t inputSize[11] =  {1, 2, 2, 3, 6, 8, 9, 2, 1, 2, 1}; //<< this hides parameter. And has totally different type.
           const uint8_t window = 5; // Also hiding parameter
           {
             const int inputSeries[] = {1, 2, 2, 3, 6, 8, 9, 2, 1, 2,1}; // again hiding

             double window = 5;  // more hiding of variables and parameters
             double c = 2.0; // Where does this value come from?
             double d = 2.0;

             for(int i = 0; i < window; i++) // Same loop variable as outer loop.
             {
               c += inputSeries[i];
               d = c / window;
             }

             return true;  // You return after first iteration of outer loop.
// No printf so far
// No value assigned to output[] so far.
// The only result is return value true.
           }
         }
       }
   }
 }

您使用不同的類型將window隱藏了兩次。 除非那是一些混淆競賽,否則這是不可以的。 其他參數也隱藏在不同類型的變量中。

外循環完全沒有效果,因為它永遠不會達到第二次迭代。

一次又一次地檢查循環內的參數(如果它被多次執行)是浪費 CPU 時間。

讓我們重新排序您的代碼並刪除一些奇怪的東西(代碼未經測試,任何發現拼寫錯誤的人都可以保留它們。;))

void Array_MovingAverage(const int inputSeries[], size_t inputSize, size_t window, float output[],
                         size_t outputSize) {
   if ( window < inputSize
     && inputSeries != NULL && output != NULL
     && outputSize >= inputSize ) {

      double c = 0.0;
      double avg;
      int i;

      // first fill partial window at begin
      for (int i = 0; i < window; i++)
      {
         c += inputSeries[i];
         avg = c / (i+1);
         output[i] = avg;
      }

      // Then handle full windows until we reach the end
      // c now contains sum of entries 0..window-1
      // i points to entry 'window'
      for ( ; i < inputSize; i++)
      {
         // Move the window by adding 1 new element and remove 1 old element
         c += inputSeries[i];
         c -= inputSeries[i-window]
         avg = c / window;
         output[i] = avg;
      }
   }
}

int main(void)
{
   int    input[] = {1, 2, 2, 3, 6, 8, 9, 2, 1, 2,1};
   size_t Size = sizeof(input)/(input[0]);
   float  output[Size] = {0};

   Array_MovingAverage(intput, Size, 5, output, Size);

   printf("Moving avarage:\n");
   for (int i = 0; i < Size; i++)
   {
      printf("%d ", input[i]);
   }

   for (int i = 0; i < Size; i++)
   {
      printf("%f ", (int)(output[i]+0.5));
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM