У меня есть код для преобразования значения времени, возвращаемого из 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 бит (а двойной должен иметь возможность хранить 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 дней, поэтому значение больше, чем я привык? Таким образом, это похоже на проблему точности разделения с большими номерами, но это все еще не объясняет, почему разделение по-прежнему было правильным в окне «Часы». Использует ли он более высокоточный тип, чем двойной для его результатов?