2011-01-22 70 views
2
unsigned GetLowestBitPos(unsigned value) 
{ 
    double d = value^(value - !!value); 
    return (((int*)&d)[1]>>20)-1023; // This is what I really need help understanding. 
} 

它在我看來,代碼鑄造了一個雙指針到一個整數的指針。我不確定[1]用於什麼。然後它看起來像我們右移了20位這個代碼如何獲得最低位的​​位置?

我希望對此代碼有任何幫助。 自從我用C++進行編程以來,我已經有一段時間了,我正在嘗試爲可編程邏輯控制器(PLC)編寫邏輯,以便在可能的情況下執行相同的操作。

感謝您的幫助

+3

用unsigned long long替換double,它應該減少混淆。沒有神奇的雙精度IEEE754相關的計算正在進行,因爲它的8個字節(64位)的數據沒有其他用處,所以這裏使用了double。 – 2011-01-22 06:31:10

回答

6

讓我們一次一步。第一:

double d = value^(value - !!value); 

如果value = 0,那麼這個計算結果爲0 ^(0 - 0),所以d是0 如果value != 0,那麼這個計算結果爲值^(值 - 1)。這具有將最低一位和最低零位設置爲1並將所有其他位設置爲零的效果。例如:

value = 010100100 
d  = 000000111 

這是因爲(value - 1)相同value,除了零個比特的最低串成爲一體,和下一個位變爲零,由於攜帶

value  = 010100100 
value - 1 = 010100011 
XOR value = 000000111 

在任何情況下,d加載了浮點數這個值。下一行:

return (((int*)&d)[1]>>20)-1023; 

這將提取浮點指數並返回偏差。請注意,這假設一個小端系統,如x86;在一個大的endian系統上,你需要使用[0]。它還對int s和doubles的大小進行了假設 - 特別是假定32位整數和64位IEEE浮點數用於雙精度浮點數。

這裏的關鍵是,非規格化IEEE浮點值(在雙和一個32位int將始終是非規格化)具有表示最終看起來有點像1.xxxxxxxx * 2^(e-1023),其中xxxxxxxx是小數部分,e是指數。既然你已經把最感興趣的位置排列成最高位的那個位,那麼它就會隨着你所尋找的值而指數增加。也就是說,你可能無法在PLC上使用它 - 儘管這是一個非常聰明的黑客攻擊,但如果你有一個硬件FPU,它甚至只是遠程有效;甚至在x86系統上也有faster built-in integer operationsthis SO question還有其他一些技巧;你可能會在那裏找到更快的。您的PLC也可能有一個內置操作,可以在一條指令中執行此操作。