用 C语言实现去掉最大值最小值,再求平均值的算法

一般情况下,我们会先收集并存储所有数据,然后将这些数据全部传递给一个函数。该函数会找出其中的最大值和最小值,并对其他数据进行累加,最后求出平均值。

现在我们来考虑另一种情况:周期性地获取一个数据,当达到指定数量后,直接计算出平均值,而不保存实时数据。

一、实现

typedef struct
{
    uint8_t u8Cnt;
    uint16_t u16Min;
    uint16_t u16Max;
    uint32_t u32Sum;
    uint16_t u16Avg;
} Avg1Word_t;

#define mMath_Avg1Init(pObj)                    {(pObj)->u8Cnt = 0; (pObj)->u16Avg = 0;}

首先,我们定义一个上述结构体的变量,并调用 mMath_Avg1Init 对其进行初始化;

bool Math_Average1Apply(Avg1Word_t *pObj, uint16_t u16New, uint8_t u8Num)
{
    if (pObj->u8Cnt == 0)
    {
        pObj->u16Min = u16New;
        pObj->u16Max = u16New;
        pObj->u32Sum = u16New;
    }
    else
    {
        if (pObj->u16Min > u16New)
        {
            pObj->u16Min = u16New;
        }
        if (pObj->u16Max < u16New)
        {
            pObj->u16Max = u16New;
        }

        pObj->u32Sum += u16New;
    }

    pObj->u8Cnt++;
    if (pObj->u8Cnt >= u8Num)
    {
        if (pObj->u8Cnt > 2)
        {
            pObj->u32Sum -= pObj->u16Min;
            pObj->u32Sum -= pObj->u16Max;
            pObj->u8Cnt -= 2;
        }

        pObj->u16Avg = pObj->u32Sum / pObj->u8Cnt;
        pObj->u8Cnt = 0;

        return true;
    }

    return false;
}

其次,每当有新数据产生时,我们会调用 Math_Average1Apply 函数,并将新数据u16New传入该函数。

同时,我们还会指定一个总数u8Num,例如 u8Num = 10,表示调用 Math_Average1Apply 函数10次后,产生一个新的平均值。在这 10 次调用中,我们会去掉最大值和最小值,然后对剩余的 8 个数求平均值;

当 u8Num <= 2 时,不会去掉最大值和最小值,而是直接对所有数据求平均值;

#define mMath_GetAvg1Value(pObj)                ((pObj)->u16Avg) // Get average value

最后,当 Math_Average1Apply 函数返回 true 时,可以使用以上的宏定义来获取当前的平均值。

二、验证

用于验证这个算法的程序如下:我们循环调用 Math_Average1Apply 函数若干次,当函数返回 true 时,打印出相应的结果。

static void TestMath_privAverage1(uint16_t * pBuf, uint8_t u8Len)
{
    Avg1Word_t oAvg;
    uint8_t u8Cnt;

    mMath_Avg1Init(&oAvg);

    for (u8Cnt = 0; u8Cnt < u8Len; u8Cnt++)
    {
        // 原始数据
        printf("%d ", pBuf[u8Cnt]);
        if (Math_Average1Apply(&oAvg, pBuf[u8Cnt], u8Len))
        {
            // 输出平均值
            printf("-> Average: %d\n", mMath_GetAvg1Value(&oAvg));
        }
    }
}

你可以修改 trBuffer1 数组的内容,进一步验证这个算法的正确性。

static uint16_t trBuffer1[] = { 0x0123, 0x4567, 0x89ab, 0xcdef };
TestMath_privAverage1(trBuffer1, ARRAY_SIZE(trBuffer1));

完整的代码和验证程序,请参考 chip_c: 芯片C语言框架和实用程序集合

你可能感兴趣的:(c语言,算法)