NTP的時間戳的LSW轉換為unix的usec
阿新 • • 發佈:2019-01-09
關於NTP協議的介紹就不囉嗦了,網上已經有很多介紹的文章
這次寫的是NTP 時間戳裡面的LSW欄位到unix的usec的轉換
NTP的時間戳有兩個32位數分別是:MSW和LSW,
MSW以秒為單位
LSW以232ps(皮秒)為單位
要進行轉換,首先得知道兩個數值之間的關係!!!1LSW=232ps(皮秒)是怎樣來的?
找到了這篇章文章:點選開啟連結
說是因為32位的精度只有:2^32 = 4294967296 ≈ 4.29*10^9
而1秒就有10^12 ps
1s = 10^3 ms = 10^6 us = 10^9 ns = 10^12 ps
顯然32位的精度 無法準確表示到1ps
於是有:(10^12)ps /(2^32)≈232ps = 1 LSW
知道關係後就簡單了:
先將LSW乘以232轉為ps,然後ps除以10^6就得到us了於是有:usec = lsw * 232/1000000
下面是實現的程式碼:
/*
計算LSW轉usec
因為232本身是大約數,所以用232來計算出來的結果會有誤差
*/
unsigned int USEC_0 (unsigned int lsw)
{
return (unsigned int)((unsigned long)lsw*232/1000000);
}
/* 用浮點數能提高精度
(10^12)/(2^32)≈ 232.83064365386962890625
*/
unsigned int USEC_1 (unsigned int lsw)
{
double per = 232.83064365386962890625;
return (unsigned int)(lsw*per/1000000);
}
最後貼出一條網上看到的能實現同樣功能的程式碼,神奇的地方是它將除法巧妙的轉換成為移位和乘法,這是編譯器做的優化,直接就在程式碼上實現編譯器的優化,看來寫這程式碼的是一位大神。
/* 下面這條式是根據: ((lsw * 232 * 4835703278458516699)>>82)一步步化簡得到的 (lsw * 232 * 4835703278458516699)>>82 = (lsw*(2^32(2^32*2^6-3)-58708460102150527368))>>82 =N個步驟 =(((lsw) >> 12) - 759 * ((((lsw) >> 10) + 32768) >> 16)); */ unsigned int USEC (unsigned int lsw) { return (((lsw) >> 12) - 759 * ((((lsw) >> 10) + 32768) >> 16)); }