簡體   English   中英

帶時間計數的負數

[英]Negative numbers with time count

我想知道為什么我得到負值我已嘗試過多種數據類型(浮點數,雙倍長雙等)但結果是..或其負數或零或NA。 這是一個檢查商店中客戶的中等服務時間的功能,我只發布了問題代碼的相關部分。 Ty提前

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);

}

問題是你不要將dif init初始化為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.000001而不是0.0000001。 不易出錯,簡單地除以1e6。

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

  • 無法初始化diff

  • 您應該避免使用浮點運算進行累積。 這是不必要的,並且會累積精度誤差,並且長雙倍是多余的,因為您只需要幾秒到微秒的分辨率。

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

以下修復了除上述最后一個問題之外的所有問題(以后的解決方案):

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的系統時鍾的分辨率未定義,並且可能無法在系統上提供微秒級分辨率。 如果“DO A BUNCH OF STUFF”花費較少的時間分辨率,您將獲得零或時鍾分辨率的答案。

您可以通過以下方式確定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中的-Wall -Werror或VC ++中的\\W4 \\WX 您還應該使用源級符號調試器來查找代碼中的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM