Преобразование 100-наносекунд в миллисекундную путаницу

ПРИМЕЧАНИЕ. Скорее всего, это вопрос о неправильной математике, а не вопрос о системном вызове Windows, как описано в вопросе.

Мы работаем с вызовом GetSystemTimeAsFileTime() win32 и видим странные, на мой взгляд, результаты и нуждаемся в некоторых разъяснениях. Из MSDN в структуре FILETIME https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx

Содержит 64-разрядное значение, представляющее количество 100-наносекундных интервалов с 1 января 1601 года (UTC).

Согласно нашему прочтению этого описания, возвращаемое значение представляет собой количество секунд интервала 10e-8. Предполагая, что это правильно, следующая функция должна возвращать системное время в миллисекундах.

DWORD get_milli_time() {
    FILETIME f;
    ::GetSystemTimeAsFileTime(&f);
    __int64 nano = (__int64(f.dwHighDateTime) << 32LL)
                  + __int64(f.dwLowDateTime);
    return DWORD(nano / 10e5);
    }

Однако простой модульный тест показывает, что это неверно, приведенный ниже код печатает «Failed»:

DWORD start = get_milli_time();
::Sleep(5000);  // sleep for 5-seconds
DWORD end = get_milli_time();
// test for reasonable sleep variance (4.9 - 5.1 secs)
if ((end - start) < 4900 || (end - start) > 5100) {
    printf("Failed\n");
    }

Согласно этому сообщению SO Получение текущего время (в миллисекундах) от системных часов в Windows?, правильных результатов можно добиться, изменив наше деление на:

return DWORD(nano / 10e3);

Если мы используем это значение, мы получим правильный результат, но я не могу понять, почему.

Мне кажется, что для преобразования из 10e-8 в 10e-3 надо разделить на 10e5. Это, по-видимому, подтверждается следующим расчетом:

printf("%f\n", log10(10e-3 / 10e-8));

Который возвращает 5 (как я и ожидал).

Но почему-то я ошибаюсь — но будь я проклят, если увижу, где ошибся.


person user590028    schedule 28.03.2016    source источник
comment
Вы пытались вызвать get_milli_time() дважды с интервалом около 5 секунд и посмотреть на значения, которые он дает?   -  person Beta    schedule 28.03.2016


Ответы (1)


Ваша математика действительно ошибочна, как и ваше понимание «рабочего» кода.

В секунде 107 интервалов по 100 наносекунд, 104 в миллисекунде. В записи с плавающей запятой это 1.0e4. 10e3 — это странный способ написания 1e4.

«Правильный» (в смысле наиболее эффективный, но при этом остающийся выразительным) код будет

return DWORD(hundrednano * 1.0e-4);
person Ben Voigt    schedule 28.03.2016
comment
Возможно ошибка в записи. 10^3 с 10e3, хотя на самом деле это 10^3 = 1e3 - person Nacho; 28.03.2016
comment
@Nacho: Не может быть, определенно. - person Ben Voigt; 28.03.2016
comment
Моя ошибка заключалась в неправильной e научной нотации. Спасибо. - person user590028; 28.03.2016