此代碼利用浮點數的IEEE 754格式結構。該結構本身是專門爲此類操作而設計的,以便快速進行比較操作。
每個單精度IEEE 754號有三個部分(爲了從MSB到LSB):
- 符號位
- 指數部分(8個比特)
- 有效數尾數的(23個比特)
f1
大於f2
如果:
f1
爲正,f2
爲負
f1
和f2
都是積極的,但f1
具有更大的指數比f2
f1
和f2
均爲正,並且具有相同的指數,但f1
比f2
- 大尾數前兩個相反
f1
和f2
是負數
如果浮點數是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
呈陽性,那麼t1
是0
和(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都有專用指令來執行硬件中的帶符號比較。
「但速度更快」。 - 比什麼更快? –
我想你可能會拉[這個有點](http://stackoverflow.com/questions/10381927/efficient-floating-point-comparison-cortex-a8)。 – Bart
@Bart是的,我現在有一段時間在實際情況下嘗試這些代碼,但我仍然不明白它是如何工作的。 – Alex