查找数组的平均值

时间:2015-06-08 23:21:41

标签: c arrays algorithm average

我真的很难从数组中找到加权和。 我有一个叫做频率[28]的数组(1D大小28)和相同大小的相同索引数组,叫做peak [28]。数组总是有一个值或零。我想要实现的是通过数组,从频率和幅度数组中检索两个值,同时忽略零。另外,我并没有试图找到整个阵列的加权平均值。

我想我不是很清楚。

例如说

frequency[n] = [0,0,0, a,b, 0,0,0, c,d,e, 0,0, f]
peak[n] = [0,0,0, z,y, 0,0,0, x,w,v, 0,0, u]

因此,我想忽略前三个区,因为它们为零,并找到(a,b)与(z,y)配对的加权平均值,然后忽略接下来的三个区间,然后再次找到(c,d, e)与(x,w,v)等配对。
请注意,我在数组中的值(大小是固定的)不是固定的。可能出现值的索引总是不同的。

我已经附加了检索数组的代码片段。 任何建议或指导都会有很大的帮助!

// peak search
threshold = 0;
for (ctr=0; ctr<n1; ctr++)
{   
    peak[ctr] = 0; // initialise arrays
    freq_bin[ctr] =0;
    frequency[ctr] = 0;

    // magnitude calculation from fft output
    fft_mag[ctr] = 10*(sqrt((fft_output[ctr].r * fft_output[ctr].r) + (fft_output[ctr].i * fft_output[ctr].i)))/(n);
    threshold = 12; 
    if (fft_mag[ctr] >= threshold) // extract fft magnitudes only above threshold
    {
        peak[ctr] = fft_mag[ctr]; // store magnitude above threshold into peak array
        freq_bin[ctr] = ctr;        // location of each magnitude above threshold
        frequency[ctr] = (freq_bin[ctr]*(10989/n)); // frequency calculation from magnitude location        
    }
}

对于不对代码进行评论,我深表歉意。

  • peak[ctr]包含fft输出的峰值大小
  • frequency[ctr]包含相应的fft峰值幅度的频率值。

我有来自fft的多个峰值,输出数组看起来像这样;

peak[28] =      [0 0 0 0 0 0 0 0 0 0  14 0 0 0 0 0 0  14 0 0 0  29  74   45 0 0 0 0]
frequency[28] = [0 0 0 0 0 0 0 0 0 0 462 0 0 0 0 0 0 714 0 0 0 924 966 1008 0 0 0 0]

因此,我需要计算:

  • 平均1 =(14×462)/ 14 = 462Hz
  • 平均值2 =(14×714)/ 14 = 714Hz
  • 平均3 =(29x924 + 74x966 + 45x1008)/(29 + 74 + 45)= 938.8 Hz

2 个答案:

答案 0 :(得分:0)

您可以将其视为状态机。它一次读取一个符号,并根据它改变状态。

有两种状态:起始状态和已读取某些数据的状态。

在起始状态下,如果下一个符号为零,则保持此状态。如果没有,请处理符号并更改状态。

在另一个状态中,如果下一个符号为零,则发出结果并更改状态。如果没有,请处理它。如果在此状态下遇到结束,则发出结果。

这是一个非常干净的Python实现:

class Averager:

    def __init__(self):

        self.averages = []

        self.sumOfNumbers = 0
        self.count = 0

    def addToAverage(self, number, weight):
        self.sumOfNumbers += number * weight
        self.count += weight

    def emitAverage(self):
        self.averages.append(self.sumOfNumbers / self.count)
        self.sumOfNumbers = 0
        self.count = 0


def averagesOf(data, weights):

    averager = Averager()
    dataRead = False

    def emitIfData():
        if dataRead:
            averager.emitAverage()

    for number, weight in zip(data, weights):
        if number == 0:
            emitIfData()
            dataRead = False
        else:
            averager.addToAverage(number, weight)
            dataRead = True

    emitIfData()

    return averager.averages

print(averagesOf([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, 0, 0, 0, 0, 0, 0, 714, 0, 0, 0, 924, 966, 1008, 0, 0, 0, 0],
                 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  14, 0, 0, 0, 0, 0, 0,  14, 0, 0, 0,  29,  74,   45, 0, 0, 0, 0]))

输出:

[462.0, 714.0, 970.5405405405405]

答案 1 :(得分:0)

这里有一些近似于MCVE(How to create a Minimal, Complete, and Verifiable Example?)的代码。除此之外,我通过在非零数据集之前和之间留下一组零来压缩操作/感兴趣的数据。在这个问题中,3项加权平均值的计算似乎是错误的:

  
      
  • 平均3 =(29x924 + 74x966 + 45x1008)/(29 + 74 + 45)= 938.8 Hz
  •   
  • 平均3 =(26796 + 71484 + 45360)/ 148
  • 平均3 = 143640/148
  • 平均3 = 970.54

这与该计划的计算一致。

代码:

#include <stdio.h>

int main(void)
{
    enum { NUM_ENTRIES = 28 };

    /* Input data */
    double peak[NUM_ENTRIES] = { 0,  14, 0,  14, 0,  29,  74,   45, 0, };
    double freq[NUM_ENTRIES] = { 0, 462, 0, 714, 0, 924, 966, 1008, 0, };

    /* Output data */
    double bin_av[NUM_ENTRIES];
    int bin_lo[NUM_ENTRIES];
    int bin_hi[NUM_ENTRIES];
    int out = 0;

    int ctr = 0;
    while (ctr < NUM_ENTRIES)
    {
        /* Skip zeroed entries */
        while (ctr < NUM_ENTRIES && (peak[ctr] == 0.0 || freq[ctr] == 0.0))
            ctr++;
        if (ctr < NUM_ENTRIES)
        {
            bin_lo[out] = ctr;
            bin_hi[out] = ctr;
            double w_sum = 0.0;
            double f_sum = 0.0;
            while (ctr < NUM_ENTRIES && (peak[ctr] != 0.0 && freq[ctr] != 0.0))
            {
                bin_hi[out] = ctr;
                w_sum += peak[ctr] * freq[ctr];
                f_sum += peak[ctr];
                ctr++;
            }
            bin_av[out++] = w_sum / f_sum;
        }
    }

    for (int i = 0; i < out; i++)
        printf("%d .. %d: %6.1f\n", bin_lo[i], bin_hi[i], bin_av[i]);

    return 0;
}

示例输出:

1 .. 1:  462.0
3 .. 3:  714.0
5 .. 7:  970.5

有足够的空间来改善输出(例如,回显输入数据的相关子集并不是一个坏主意。)

有了这个框架,您可以通过从FFT输出中的值计算peakfreq中的值,而不是使用硬编码数组,来回到使场景复杂化。 / p>