У меня есть некоторый код для преобразования значения времени, возвращенного из 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 бит (и двойной должен иметь возможность хранить 52 бита без потерь)
Кроме того, кажется странным, что отладчик использовал бы другой формат для деления.
Вот некоторые результаты, которые я получил. Программа была скомпилирована в режиме отладки, режим с плавающей запятой в параметрах C ++ был установлен по умолчанию (Precise (/ 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
Кто-нибудь знает, почему точность в Watch отладчика отличается от результата в моей программе?
Обновление: я пытался вычесть 30270310439445 из timerPerformanceCounter.QuadPart перед выполнением преобразования и деления, и теперь оно кажется точным во всех случаях.
Может быть, причина, по которой я сейчас вижу только такое поведение, может быть в том, что время работы моего компьютера составляет 16 дней, поэтому значение больше, чем я привык?
Таким образом, это кажется проблемой точности деления с большими числами, но это все еще не объясняет, почему деление все еще было правильным в окне Watch.
Использует ли он более точный тип, чем double, для своих результатов?