我有一些代码可以将从QueryPerformanceCounter返回的时间值转换为以毫秒为单位的双精度值,因为这样更便于计数。
该函数如下所示:
double timeGetExactTime() {
LARGE_INTEGER timerPerformanceCounter, timerPerformanceFrequency;
QueryPerformanceCounter(&timerPerformanceCounter);
if (QueryPerformanceFrequency(&timerPerformanceFrequency)) {
return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
}
return 0.0;
}我最近遇到的问题(我不认为我以前有过这个问题,并且没有对代码进行任何更改)是结果不是很准确。结果不包含任何小数,但精度甚至低于1毫秒。
当我在调试器中输入表达式时,结果与我预期的一样准确。
我知道double不能保持64位整数的精度,但此时,PerformanceCounter只需要46位( double应该能够无损失地存储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天,所以这个值比我习惯的要大?因此,这似乎是一个大数字的除法精度问题,但这仍然不能解释为什么在监视窗口中除法仍然是正确的。它的结果是否使用比double更高精度的类型?
发布于 2009-05-24 09:00:58
谢谢,使用decimal也可能是一种解决方案。现在,我采取了一种稍微不同的方法,这种方法也运行得很好,至少只要我的程序在不重启的情况下运行不超过一周左右。我只记得当我的程序启动时的性能计数器,并在转换为双精度并进行除法之前从当前计数器中减去它。
我不确定哪种解决方案是最快的,我想我必须首先对其进行基准测试。
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();
}发布于 2009-05-23 20:59:14
阿迪恩
如果您不介意性能影响,请在执行除法之前将QuadPart数字转换为十进制而不是双精度。然后将得到的数字转换回双精度。
你对数字大小的估计是正确的。它抛弃了浮点计算的准确性。
有关这方面的更多信息,请参阅:
每个计算机科学家都应该知道的浮点算术http://docs.sun.com/source/806-3568/ncg_goldberg.html
https://stackoverflow.com/questions/902320
复制相似问题