Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What you're running into here is loss of precision in the conversion from NTP timestamp to milliseconds. When you convert from NTP to milliseconds, you're dropping part of the fraction. When you then take that value and try to convert back, you get a value that's slightly different. You can see this more clearly if you change your <code>ulong</code> values to <code>decimal</code> values, as in this test:</p> <pre><code>public static decimal GetMilliSeconds(byte[] ntpTime) { decimal intpart = 0, fractpart = 0; for (var i = 0; i &lt;= 3; i++) intpart = 256 * intpart + ntpTime[i]; for (var i = 4; i &lt;= 7; i++) fractpart = 256 * fractpart + ntpTime[i]; var milliseconds = intpart * 1000 + ((fractpart * 1000) / 0x100000000L); Console.WriteLine("milliseconds: " + milliseconds); Console.WriteLine("intpart: " + intpart); Console.WriteLine("fractpart: " + fractpart); return milliseconds; } public static byte[] ConvertToNtp(decimal milliseconds) { decimal intpart = 0, fractpart = 0; var ntpData = new byte[8]; intpart = milliseconds / 1000; fractpart = ((milliseconds % 1000) * 0x100000000L) / 1000m; Console.WriteLine("milliseconds: " + milliseconds); Console.WriteLine("intpart: " + intpart); Console.WriteLine("fractpart: " + fractpart); var temp = intpart; for (var i = 3; i &gt;= 0; i--) { ntpData[i] = (byte)(temp % 256); temp = temp / 256; } temp = fractpart; for (var i = 7; i &gt;= 4; i--) { ntpData[i] = (byte)(temp % 256); temp = temp / 256; } return ntpData; } public static void Main(string[] args) { byte[] bytes = { 131, 170, 126, 128, 46, 197, 205, 234 }; var ms = GetMilliSeconds(bytes); Console.WriteLine(); var ntp = ConvertToNtp(ms); } </code></pre> <p>This yields the following result:</p> <pre><code>milliseconds: 2208988800182.7057548798620701 intpart: 2208988800 fractpart: 784715242 milliseconds: 2208988800182.7057548798620701 intpart: 2208988800.1827057548798620701 fractpart: 784715242.0000000000703594496 </code></pre> <p>It's the ~0.7 milliseconds that are screwing things up here.</p> <p>Since the NTP timestamp includes a 32-bit fractional second (<a href="http://en.wikipedia.org/wiki/Network_Time_Protocol#NTP_timestamps" rel="nofollow">"a theoretical resolution of 2^-32 seconds or 233 picoseconds"</a>), a conversion to integer milliseconds will result in a loss of precision.</p> <h2>Response to Update:</h2> <p>Adding milliseconds to the NTP timestamp wouldn't be quite as simple as adding the integer parts and the fraction parts. Think of adding the decimals 1.75 and 2.75. 0.75 + 0.75 = 1.5, and you'd need to carry the one over to the integer part. Also, the fraction part in the NTP timestamp is not base-10, so you can't just add the milliseconds. Some conversion is necessary, using a proportion like <code>ms / 1000 = ntpfrac / 0x100000000</code>.</p> <p>This is entirely untested, but I'd think you'd want to replace your <code>intpart +=</code> and <code>fracpart +=</code> lines in <code>AddMilliSeconds</code> to be more like this:</p> <pre><code>intpart += millis / 1000; ulong fractsum = fractpart + (millis % 1000) / 1000 * 0x100000000L); intpart += fractsum / 0x100000000L; fractpart = fractsum % 0x100000000L; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload