1. 程式人生 > >NTP的時間戳的LSW轉換為unix的usec

NTP的時間戳的LSW轉換為unix的usec

關於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));
}