본문 바로가기
카테고리 없음

XfGetTime 테스트 , 정수형의 한계

by ictlab 2009. 11. 16.

현재 장비에서 쓰고 있는 QueryPerformanceCounter를 이용한 시간 계산의 한계점을 한번 테스트 해 보았습니다.
XfGetTime에서 double 형 리턴값을 받아서 쓸때는 문제가 없는데
XfGetTime을 int 형으로 변환해서 사용할때는 PC를 오래켜둘때 문제가 발생할 가능성이 발견되었습니다.

아래는 테스트를 위한 프로젝트 입니다.


 
//---------------------------------------------------------------------------

#include <math.h>

double XfGetTime(void)
{
  LARGE_INTEGER liEndCounter,liFrequency ;
  QueryPerformanceCounter(&liEndCounter);
  QueryPerformanceFrequency(&liFrequency);

  return (liEndCounter.QuadPart / (double)liFrequency.QuadPart) * 1000;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   String s;


   double d = XfGetTime();
   int i = d;

   Memo1->Lines->Add("XfGetTime의 결과를 실수형과 정수형으로 표시");
   s.sprintf("%lf, %d msec , %d h", d, i, i/1000/60/60);

   Memo1->Lines->Add(s);

   Memo1->Lines->Add("");
   Memo1->Lines->Add("정수형의 최대값을 계산");
   int r = pow(2,31)-1;
   s.sprintf("2^10-1 = %d, %d h , %d day", r, r/1000/60/60 , r/1000/60/60/24);
   Memo1->Lines->Add(s);


   int a = pow(2, 31 ) + 10;
   int b = pow(2, 31 ) + 20 ;

   Memo1->Lines->Add("");
   Memo1->Lines->Add( "a = 2^31 + 10 , b = 2^31 + 20 을 입력 정수형보다 큰 값을 입력") ;
   s.printf("두 수의 차이를 계산 : b - a = %d", b-a);
   Memo1->Lines->Add(s);

   Memo1->Lines->Add("");
   s.printf("double 한계 체크 : %lf", pow(2,64));
   Memo1->Lines->Add(s);

}
//----------
     




실행 결과
 

XfGetTime의 결과를 실수형과 정수형으로 표시
37635286.628977, 37635286 msec , 10 h

정수형의 최대값을 계산
2^10-1 = 2147483647, 596 h , 24 day

a = 2^31 + 10 , b = 2^31 + 20 을 입력 정수형보다 큰 값을 입력
두 수의 차이를 계산 :  b - a = 10

double 한계 체크 : 18446744073709551620.000000

결과 분석
첫번째 결과는 PC를 켜놓은지 10시간 정도되었다는 것을 보여줍니다.

두번째 결과는 4바이트 정수형으로 표현할수 있는 최대 날짜 수를 계산하려 한것인데..
시간으로 596시간 , 일수로 24일 이상이 되면 정수형의 한계를 벗어나는 결과가 나오게 됩니다.

 
세번째는 a와 b에 정수형을 벗어나는 수를 입력한후 더 큰 수를 입력한 b에서 a를 빼는 계산 결과를 보여줍니다.
두 숫자가 다 정수형을 벗어날때는 결과가 제대로 나오는 것을 알 수 있습니다.


마지막으로 double 형 데이터를 한계를 보기 위해 2의 64승 계산 결과를 printf로 출력해 봤습니다.
결과가 맞는지는 모르지만 나오기는 나오는군요..

문제가 되는 상황은 24일 동안 PC를 끄지 않고 다음과 같은 비교 구문을 사용하는 경우입니다.

 


int start = XfGetTime();

if( XfGetTime() - start > 1000 )
{
    // 에러처리
}
     

24일이 지난 시점에서 위 코드에는 start에 항상 음수가 들어가기 때문에 전체 값이 무조건 엄청나게 큰 값이 되어서 무조건 if 조건문 안으로 들어가게 됩니다.

시퀀스 코드 안에서 위 구문으로 타임 아웃 체크등을 하게 되면 계속 문제가 생길 가능성이 있으므로 특별히 주의 바랍니다.

이렇게 수정하면 문제가 없어지게 됩니다.

 


double start = XfGetTime();

if( XfGetTime() - start > 1000 )
{
    // 에러처리
}