我求解平均值的函数提供随机值

My function solving for average value delivers random values

我正在使用 MikroC 尝试对 PIC4550 进行编程以从 pH 传感器检索数据。该程序包括检索数据 40 次并使用以下函数 Average 计算其平均值

double Average(int* arr, int number)
{
    int i;
    int ave;
    int sum = arr[0];
    for(i = 0;i<number;i++)
    {
        sum=sum+arr[i];
    }
    ave = sum/number;
    return ave;
}

我的问题是它提供的随机值在大多数情况下都与正确答案相去甚远。例如,正确答案是 633,但结果是 -185。谁能指出我的错误?谢谢。我的全部代码如下

#define volt 5.00 //system voltage
#define arraylength 40 // number of data collection
#define offsetph 5   //deviate compensate

double Average(int*, int);

void main() {
     float ph_res=0;
     float pHsensor_output[40];
     double avepH;
     double pHvoltage;
     float offsetpH=0.38;  //change to actual pH offset
     float pHlevel;
     char testing[20];
     char pher[20];
     int i;
     int pH_index=0;
     UART1_Init(9600);
     ADCON1=0x00;
     CMCON=7;

     TRISA=0xFF;


   while(1){
    UART1_Write_Text("Reading pH....\r\n");
     for(i = 0; i<40; i++) {
            pHsensor_output[i] = ADC_Read(1);
            sprintf(testing,"READING: %.2f\r\n",pHsensor_output[i]);
            UART1_Write_Text(testing);
            delay_us(1000);
        }
        avepH = Average(pHsensor_output, 40);
        sprintf(testing,"AVG: %f\r\n",avepH);
        UART1_Write_Text(testing);
        pHvoltage = avepH*5/1024;
        pHlevel = 3.5*pHvoltage+offsetph;
        if(pHlevel!=pH_res){
            pH_res = pHlevel;

        }
             sprintf(pher,"pH: %f\r\n",pH_res);
            UART1_Write_Text(pher);

     delay_ms(2000);
       } }
double Average(int* arr, int number)
{
    int i;
    int ave;
    int sum = arr[0];
    for(i = 0;i<number;i++)
    {
        sum=sum+arr[i];
    }
    ave = sum/number;
    return ave;
}

一些评论指出您在求和期间有溢出的风险。如果这是一台 16 位机器,INT_MAX 是 32767。根据您的示例,您还没有接近这个,但需要注意这一点。

无论如何,您正在将值收集到 floats:

的数组中
 float pHsensor_output[40];
 ...
 pHsensor_output[i] = ADC_Read(1);

但后来将其传递给需要 ints 数组的函数:

double Average(int* arr, int number)
...
  avepH = Average(pHsensor_output, 40);

Averageint 和 returns 计算 double 的事实意味着你 可能 被截断答案,但这不是这里的问题。)

您的计算机现在正在查看一种位模式,当被视为浮点数时可能是“633”,但当被视为整数时几乎肯定不是。那么谁知道当你取它们的平均值时结果会是什么?!

尝试将您的函数更改为:

double Average(float* arr, int number)
{
    int i;
    double ave;
    double sum = 0.0; // NOTE: not arr[0];
    for(i = 0;i<number;i++)
    {
        sum=sum+arr[i];
    }
    ave = sum/number;
    return ave;
}

附录:你的编译器真的应该抱怨这个。真的保持沉默了吗? GCC 立即呕吐。

error: cannot convert ‘float*’ to ‘int*’ for argument ‘1’ to ‘double Average(int*, int)’

编辑:通过观察理解总是很好,所以我尝试了一个小例子。我的是台式机,不是 PIC,所以 int 是 32 位而不是 16 位,但希望重点是一样的....

int main()
{
    union {
        float my_float;
        int my_int;
    } hack;

    printf ("sizeof(float) %lu, sizeof(int) %lu\n", sizeof(float), sizeof(int));

    hack.my_float = 633.0;
    printf( "%f -> %d\n", hack.my_float, hack.my_int );

    int sum = 40 * hack.my_int;
    int average = sum / 40;

    printf( "sum %d  -->  %d\n", sum, average );

    return 0;
}

产量:

sizeof(float) 4, sizeof(int) 4
633.000000 -> 1142833152
sum -1531314176  -->  -38282854

这个'shows'是什么,一个好的float变成了一个疯狂的int(当相同的位模式被不同地看待时1),在那之后,所有的赌注都被取消了。显然,总和溢出,因此平均值为负;完全出乎您的意料!

1 我在示例中使用的 'union hack' 对计算机说:“获取包含 float 的内存位置并查看完全相同的内容位,但假装它是一个 int。这就是当您将指向某些浮点数的指针传递给期望指向整数的指针的函数时发生的情况。

但是如果你做一个作业 'cleanly' 你会得到你所期望的:

    int nice_int = hack.my_float;  // 633.0
    printf( "good %f  ->  %d\n", hack.my_float, nice_int );

产量:

good 633.000000  ->  633