2009-05-23 65 views
1

我有一些代碼可以將從QueryPerformanceCounter返回的時間值轉換爲以毫秒爲單位的雙精度值,因爲這更方便計算。雙精度劃分不準確(Visual C++ 2008)

功能如下:

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位整數的精度,但此時PerformanceCounter只需要46位(而double應該能夠保存52位而不丟失) 此外,它似乎很奇怪調試器將使用不同的格式進行分區。

這是我得到的一些結果。該程序被編譯在調試模式下,在C浮點模式++選項設置爲默認值(精確(/計劃生育:精確))

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天,所以價值比我以前更大? 所以它似乎是一個大數分割準確度問題,但這仍然無法解釋爲什麼分割在Watch窗口中仍然是正確的。 它的結果是否使用高於精度的雙精度類型?

回答

0

感謝,使用十進制可能會是一個解決方案了。 現在我已經採取了一種稍微不同的方法,至少只要我的程序在沒有重新啓動的情況下運行時間不超過一週左右,這種方法也可以很好地工作。 我只記得我的程序開始時的性能計數器,並在轉換爲double並進行除法之前從當前計數器中減去此值。

我不確定哪種解決方案最快,我想我必須首先進行基準測試。

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(); 
}
0

Adion,

如果你不介意的性能損失,投你QuadPart號爲十進制而不是雙執行除法之前。然後將結果數字重新加倍。

你對數字的大小是正確的。它拋出了浮點計算的準確性。

對於可能比你想知道的,看到更多的關於這一點:

什麼每臺計算機科學家應該知道關於浮點運算 http://docs.sun.com/source/806-3568/ncg_goldberg.html