我有一些代码转换从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毫秒甚至不太准确。

当我进入调试器中的表达,其结果是如我期望一样精确。

我明白,一个双不能保持一个64位整数的准确性,但在此时,只的PerformanceCounter需要46位(和双应该能够存储52位,而不损失) 此外似乎奇怪的是,调试程序将使用不同的格式做除法。

下面是一些结果我得到了。该程序被编译在调试模式下,在C浮点模式++选项被设置为默认值(精确(/ FP:精确))

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

谢谢,使用小数可能会是一个溶液太。 现在,我已经采取了稍微不同的方法,这也是行之有效的,至少只要我的程序不,无需重新启动运行超过一个星期左右的时间。 我只记得我的程序启动时的性能计数器,以及将翻番,做除法之前从当前计数器减去这一点。

我不知道该解决方案将是最快的,我想我不得不基准,第一。

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,

如果你不介意的性能损失,投你QuadPart号为十进制而不是双执行除法之前。然后将所得的数转换回双

您是对数字的大小是正确的。它抛出了浮点计算的准确性。

有关更多关于这可能比你想知道的,请参阅:

什么每台计算机科学家应该知道关于浮点运算 http://docs.sun.com/source/806-3568/ncg_goldberg。 HTML

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top