2013-12-11 51 views
0

我不知道爲什麼即時獲得負值我嘗試了多種數據類型(浮動,雙長雙等),但結果是..或其負數或零或NA。這是一個函數來檢查中等服務時間給商店中的客戶,我只發佈了相關的問題代碼部分。泰提前負數與時間計數

struct timeval timecount[MAX_COSTUMERS+1][2]; 

long double getMedium(struct timeval x[][2]){ 
     long double diff; 
     int i; 
     for(i=1;i<k.clientID;i++){ 
      diff+= ((x[i][1].tv_usec)*0.0000001 - (x[i][0].tv_usec)*0.0000001)) ; 
     } 

     return diff; 
} 

void AFUNCTION(){ // Called a bunch of times 
     k.clientID++; 
     gettimeofday(&timecount[k.clientID][0], NULL); 

    // DO A BUNCH OF STUFF 


     gettimeofday(&timecount[k.clientID][1], NULL); 


} 

void main () { 

    long double aux; 
    aux=getMedia(timecount); 
    printf("%LG \n",aux); 

} 
+0

對'getMedia'的調用應該是'getMedium'還是一個不同的函數?「diff」累加表達式中的圓括號不匹配,所以這不是真正的代碼 - 我們可以解決您無法解決的問題;如果我們能看到真正的代碼,那麼就不會有問題! – Clifford

+0

字段'tv_usec'可能是'long'。 '0.0000001'當然是一個'雙'。所以'diff + = ...'的右邊只能用'double'精確數學來完成。然而,代碼以「long double」累加。考慮「0.0000001L」的統一精度。 – chux

回答

0

你至少有三個錯誤,一個不明智的做法(除了使用global data就是!),和一個基本的設計缺陷:

  • 如果你想在微秒的答案,那麼你需要0.000001不0.0000001繁殖。較少的錯誤傾向於簡單地除以1e6。

  • 您還沒有使用過tv_sec的會員; tv_usec會在第二秒開始時回滾到零,所以如果開始時間在前一秒,您可能會得到一個負值 - 您當然不會得到正確的答案。

  • 未初始化diff

  • 您應該避免累積浮點運算。這是沒有必要的,並且會積累精確的錯誤,並且在這裏,long double是多餘的,因爲您只需要幾秒到幾微秒的分辨率。

  • 即使您修復了第二個轉換問題,如果您的開始和結束恰好在午夜的任何一側,仍然存在問題。

以下修復所有,但最後的上面(解決以後)的問題:

double getMedium(struct timeval x[][2]) 
{ 
    unsigned long long diff = 0 ; 
    int i ; 
    for(i = 1; i < k.clientID; i++) 
    { 
     unsigned long long start_usec = x[i][0].tv_usec * 1000000ULL + x[i][0].tv_usec ; 
     unsigned long long end_usec = x[i][1].tv_usec * 1000000ULL + x[i][1].tv_usec ; 
     diff += end_usec - start_usec ; 
    } 

    return diff/1.0e6 ; 
} 

用於gettimeofday系統時鐘的決議是不確定的,並且可能不提供微秒的決議在你的系統上。如果「做一團亂七八糟」所需的時間少於時鐘分辨率,您將得到零或時鐘分辨率的答案。

您可確定由gettimeofday由時鐘的分辨率:

#include <stdio.h> 
#include <sys/time.h> 

int main() 
{ 
    struct timeval t ; 
    unsigned long long start_usec ; 
    unsigned long long end_usec ; 
    gettimeofday(&t, 0) ; 
    start_usec = t.tv_sec * 1000000ULL + t.tv_usec ; 

    do 
    { 
     gettimeofday(&t, 0) ; 
     end_usec = t.tv_sec * 1000000ULL + t.tv_usec ; 
    } while(start_usec == end_usec) ; 

    printf("Clock resolution = %u microsecond(s)", end_usec - start_usec) ; 

    return 0 ; 
} 

當然你也可以大大使用標準庫clock()功能簡化了這個代碼,這將幾乎肯定具有相同的分辨率爲gettimeofday() (檢查CLOCKS_PER_SEC的定義是肯定的),但沒有第二個或每天環繞的相關問題。

#include <time.h> 

double getMedium(struct timeval x[][2]) 
{ 
    time_t diff = 0 ; 
    int i ; 
    for(i = 1; i < k.clientID; i++) 
    { 
     time_t start_time = clock() ; 
     time_t end_time = clock() ; 
     diff += end_time - start_time ; 
    } 

    return (diff * CLOCKS_PER_SEC)/1.0e6 ; 
} 

你會在將來做好設置你的編譯器的高警戒水位和警告被視爲錯誤,-Wall -Werror在GCC或\W4 \WX在VC++爲例。您還應該使用源代碼級符號調試器來查找代碼中的問題。

2

的問題是你不用來初始化DIF爲0。書中有垃圾數據...

double getMedium(struct timeval x[][2]){ 
    double diff =0; 
    int i; 
    for(i=1;i<k.clientID;i++){ 
     diff+= ((x[i][1].tv_usec)*0.0000001 - (x[i][0].tv_usec)*0.0000001)) ; 
    } 

    return diff; 
} 
+0

仍然是負數:( – Noize

+0

@Noize這實際上不應該編譯有額外的)在差異線上。 –

+1

@Noize是否有任何東西阻止你做'(x [i] [1] .tv_usec - x [i] [0] .tv_usec)* 0.0000001'?在數學上它們是相同的,但計算上稍微有效一些。另外,如果你認爲'diff'被錯誤地計算出來,'printf'或者兩個將非常quiclky告訴你問題出在哪裏...... – nonsensickle