문제

QueryPerformanCecocounter에서 리턴 된 시간 값을 밀리 초의 이중 값으로 변환하는 코드가 있습니다.

함수는 다음과 같습니다.

double timeGetExactTime() {
    LARGE_INTEGER timerPerformanceCounter, timerPerformanceFrequency;
    QueryPerformanceCounter(&timerPerformanceCounter);
    if (QueryPerformanceFrequency(&timerPerformanceFrequency)) {
        return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
    }
    return 0.0;
}

내가 최근에 겪고있는 문제 (이전 에이 문제가 있었으며 코드가 변경되지 않았다고 생각합니다)는 결과가 그다지 정확하지 않다는 것입니다. 결과에는 소수성이 포함되어 있지 않지만 1 밀리 초보다 훨씬 덜 정확합니다.

디버거에서 표현식을 입력하면 결과가 예상만큼 정확합니다.

나는 더블이 64 비트 정수의 정확도를 유지할 수 없다는 것을 이해하지만, 현재로서는 성능이 46 비트 만 필요하다 (그리고 더블은 손실없이 52 비트를 저장할 수 있어야한다) 더 나아가서 디버거가 사용하는 것은 이상하게 보인다. 부서를 수행 할 다른 형식.

다음은 내가 얻은 몇 가지 결과입니다. 이 프로그램은 디버그 모드로 컴파일되었으며 C ++ 옵션의 부동 소수점 모드는 기본값으로 설정되었습니다 (Precise (/FP : Precise)).

timerPerformanceCounter.QuadPart: 30270310439445
timerPerformanceFrequency.QuadPart: 14318180
double perfCounter = (double)timerPerformanceCounter.QuadPart;
30270310439445.000

double perfFrequency = (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
14318.179687500000

double result = perfCounter / perfFrequency;
2114117248.0000000

return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
2114117248.0000000

Result with same expression in debugger:
2114117188.0396111

Result of perfTimerCount / perfTimerFreq in debugger:
2114117234.1810646

Result of 30270310439445 / 14318180 in calculator:
2114117188.0396111796331656677036

내 프로그램의 결과와 비교하여 디버거 시계에서 정확도가 왜 다른지 아는 사람이 있습니까?

업데이트 : TimerperFormanCecounter.quadPart에서 변환 및 부서를 수행하기 전에 30270310439445를 공제하려고 시도했지만 현재 모든 경우에 정확한 것으로 보입니다. 어쩌면 내가이 행동 만보고있는 이유는 컴퓨터의 가동 시간이 이제 16 일이기 때문에 값이 내가 익숙한 것보다 더 크기 때문일 수 있습니까? 따라서 많은 수의 부서 정확도 문제 인 것처럼 보이지만 여전히 시계 창에서 디비전이 여전히 올바른 이유를 설명하지 않습니다. 결과에 대해 더블보다 높은 정밀 유형을 사용합니까?

도움이 되었습니까?

해결책 2

고마워요, 10 진수를 사용하는 것도 해결책이 될 것입니다. 지금은 약간 다른 접근 방식을 취했는데,이 방법은 적어도 내 프로그램이 다시 시작하지 않고 일주일 이상 실행되지 않는 한 잘 작동합니다. 프로그램이 시작된 시점의 성능 카운터를 기억하고,이를 현재 카운터에서 빼기 전에 두 배로 변환하고 부서를 수행합니다.

어떤 솔루션이 가장 빠른지 잘 모르겠습니다. 먼저 벤치마킹해야한다고 생각합니다.

bool perfTimerInitialized = false;
double timerPerformanceFrequencyDbl;
LARGE_INTEGER timerPerformanceFrequency;
LARGE_INTEGER timerPerformanceCounterStart;
double timeGetExactTime()
{
    if (!perfTimerInitialized) {
        QueryPerformanceFrequency(&timerPerformanceFrequency);
        timerPerformanceFrequencyDbl = ((double)timerPerformanceFrequency.QuadPart) / 1000.0;
        QueryPerformanceCounter(&timerPerformanceCounterStart);
        perfTimerInitialized = true;
    }

    LARGE_INTEGER timerPerformanceCounter;
    if (QueryPerformanceCounter(&timerPerformanceCounter)) {
        timerPerformanceCounter.QuadPart -= timerPerformanceCounterStart.QuadPart;
        return ((double)timerPerformanceCounter.QuadPart) / timerPerformanceFrequencyDbl;
    }

    return (double)timeGetTime();
}

다른 팁

adion,

성능이 히트를 신경 쓰지 않으면 디비전을 수행하기 전에 쿼드 파트 번호를 더블 대신 10 진수로 시전하십시오. 그런 다음 결과 숫자를 다시 두 배로 돌리십시오.

당신은 숫자의 크기에 대해 맞습니다. 부동 소수점 계산의 정확도를 벗어납니다.

아마 알고 싶었던 것보다 이것에 대한 자세한 내용은 다음을 참조하십시오.

모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 것http://docs.sun.com/source/806-3568/ncg_goldberg.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top