讓我們一次一步。第一:
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 operations。 this SO question還有其他一些技巧;你可能會在那裏找到更快的。您的PLC也可能有一個內置操作,可以在一條指令中執行此操作。
用unsigned long long替換double,它應該減少混淆。沒有神奇的雙精度IEEE754相關的計算正在進行,因爲它的8個字節(64位)的數據沒有其他用處,所以這裏使用了double。 – 2011-01-22 06:31:10