2012-06-19 87 views
1

有是應該使2個浮點值之間的比較,但速度比(在Cortex-A8的EG)在某些特定情況下經常比較C代碼的解釋

int isGreater(float* f1, float* f2) 
{ 
    int i1, i2, t1, t2; 

    i1 = *(int*)f1; // reading float as integer 
    i2 = *(int*)f2; // reading float as integer 

    t1 = i1 >> 31; 
    i1 = (i1^t1) + (t1 & 0x80000001); 

    t2 = i2 >> 31; 
    i2 = (i2^t2) + (t2 & 0x80000001); 

    return i1 > i2; 
} 

有人能解釋下面的函數它是如何工作的?

+2

「但速度更快」。 - 比什麼更快? –

+2

我想你可能會拉[這個有點](http://stackoverflow.com/questions/10381927/efficient-floating-point-comparison-cortex-a8)。 – Bart

+0

@Bart是的,我現在有一段時間在實際情況下嘗試這些代碼,但我仍然不明白它是如何工作的。 – Alex

回答

5

此代碼利用浮點數的IEEE 754格式結構。該結構本身是專門爲此類操作而設計的,以便快速進行比較操作。

每個單精度IEEE 754號有三個部分(爲了從MSB到LSB):

  • 符號位
  • 指數部分(8個比特)
  • 有效數尾數的(23個比特)

f1大於f2如果:

  • f1爲正,f2爲負
  • f1f2都是積極的,但f1具有更大的指數比f2
  • f1f2均爲正,並且具有相同的指數,但f1f2
  • 大尾數前兩個相反f1f2是負數

如果浮點數是two's complement表示形式,則可以將兩個浮點數作爲整數進行比較。不幸的是,IEEE 754不使用二進制補碼來表示負數,這就是爲什麼此代碼執行轉換以便能夠將數字作爲有符號整數進行比較。

這裏是什麼樣的每一行代碼確實一步步解說:

i1 = *(int*)f1; // reading float as integer 
i2 = *(int*)f2; // reading float as integer 

這一次使用的事實,在大多數32位系統sizeof(int) == sizeof(float)讀取浮點數到正規簽署整數變量。

t1 = i1 >> 31; 

這一個提取f1的符號位。如果f1爲負,則其最高有效位將爲1,因此i1將爲負值。將它向右移動31位可以保留符號,因此如果i1爲負數,則t1的所有位都將設置爲1(等於-1)。如果f1爲正,它的符號位將爲0,最後t1將等於0

i1 = (i1^t1) + (t1 & 0x80000001); 

如果符號位爲1這條線將執行轉換爲二進制補碼錶示,如果f1爲陰性。

這裏是它如何工作的:如果f1呈陽性,那麼t10(i1^t1)也只是i1(t1 & 0x80000001)0並最終i1將只保留其原始值。如果f1爲負數,則t1將所有位設置爲1,並且RHS上的第一個表達式將是i1的位反轉,第二個表達式將等於0x80000001。這種方式i1將被轉換爲其位反轉,並且將添加1。但是這將導致一個正數,因爲MSB將被清除,這就是爲什麼0x80000000也被添加來保持數字爲負。

t2 = i2 >> 31; 
i2 = (i2^t2) + (t2 & 0x80000001); 

f2執行與上述相同的操作。

return i1 > i2; 

只是比較兩個結果簽署整數。大多數CPU都有專用指令來執行硬件中的帶符號比較。