带时间计数的负数

时间:2013-12-11 19:57:55

标签: c shell unix time

我想知道为什么我得到负值我已尝试过多种数据类型(float,double long double等),但结果是..或其负数或零或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);

}

2 个答案:

答案 0 :(得分:2)

问题是你没有将div初始化为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;
}

答案 1 :(得分: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的系统时钟分辨率未定义,可能无法在系统上提供微秒级分辨率。如果“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 ;
}

您将来可以很好地将编译器的警告级别设置为高,并将警告视为错误,例如GCC中的-Wall -Werror或VC ++中的\W4 \WX。您还应该使用源级符号调试器来查找代码中的问题。