[英]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);
但后來將其傳遞給一個需要int
數組的函數:
double Average(int* arr, int number)
...
avepH = Average(pHsensor_output, 40);
( Average
使用int
計算並返回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;
}
附錄:你的編譯器真的應該抱怨這個。 真的保持沉默了嗎? 海灣合作委員會立即嘔吐。
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
這“顯示”的是,一個漂亮的float
變成了一個瘋狂的int
(當相同的位模式以不同的方式看待時1 ),然后,所有的賭注都結束了。 顯然,求和溢出,因此平均值為負; 根本不是你所期望的!
1我在我的例子中使用的'聯合黑客'對計算機說:“取一個包含float
的內存位置並查看完全相同的位,但假裝它是一個int
。這就是當你將一個指向一些浮點數的指針傳遞給一個需要指向整數的指針的函數。
但是,如果您“干凈地”完成任務,就會得到您期望的結果:
int nice_int = hack.my_float; // 633.0
printf( "good %f -> %d\n", hack.my_float, nice_int );
產量:
good 633.000000 -> 633
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.