NOTE: This is likely a question about flawed math, rather then a question about the a windows system call as described in the question.
We are working with with the GetSystemTimeAsFileTime()
win32 call, and seeing what I think are strange results and was looking for some clarification. From MSDN on the FILETIME structure https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx
Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
According to our read of this description, the value returned is the number of 10e-8 interval seconds. Assuming this is correct, then the following function should return the system time in milliseconds.
DWORD get_milli_time() {
FILETIME f;
::GetSystemTimeAsFileTime(&f);
__int64 nano = (__int64(f.dwHighDateTime) << 32LL)
+ __int64(f.dwLowDateTime);
return DWORD(nano / 10e5);
}
A simple unittest however shows this is incorrect, the below code prints "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");
}
According to this SO post Getting the current time (in milliseconds) from the system clock in Windows?, the correct results can be achieved by changing our division to:
return DWORD(nano / 10e3);
If we use this value, we get the correct result, but I can't understand why.
It seems to me that to convert from 10e-8 to 10e-3, we should divide by 10e5. This would seem to be borne out by the following calculation:
printf("%f\n", log10(10e-3 / 10e-8));
Which returns 5 (as I expected).
But somehow I'm wrong -- but I'll be darned if I can see where I've gone wrong.
Your math is indeed flawed, and so is your understanding of the "working" code.
There are 107 100-nanosecond intervals in a second, 104 in a millisecond. In floating-point notation, this is 1.0e4
. 10e3
is a weird way of writing 1e4
.
The "right" (in a sense of most efficient while remaining expressive) code would be
return DWORD(hundrednano * 1.0e-4);