2013-06-04 21 views
6
float length = 32.32f; 
long i = *(long*)&length ; // casting a float pointer to a long pointer... 
i >>= 1; // right shift i but 1 ... or div by 2 
length = *(float*)&i; // is this necessary? 

印刷長度給出:0.0C++比特移位的浮子

最終的結果應該是:16.16;

這個想法是從http://en.wikipedia.org/wiki/Fast_inverse_square_root。我試圖理解代碼的一部分是浮法中的長時間被取出並按位操作執行它。我猜的重點是通過避免分支來提高性能?

上述代碼失敗。任何人都可以告訴我我做錯了什麼?我的印象是這樣簡單,只要將long存儲在float中並對其進行操縱,這是錯誤的嗎?

我發現了一些有趣的事情,如果我的代碼更改爲:

float length = 32.32f; 
long i = *(long*)&length ; 
i = 0x5f3759df - (i >> 1); 
length = *(float*)&i; 

增加這個數(0x5f3759df)的組合。

打印輸出長度* 100給出:17.0538 //近似值16.16
嘗試使用不同的長度給出相同的結果。

例如:長度= 100;結果是:10.3299 ?? //幾乎...

+0

你爲什麼不直接在'float'上操作?如果試圖對同一個變量(通過不同的類型)進行操作,爲什麼你會覺得有什麼變化? –

+1

那麼按位運算更快吧?原因並不重要,我只是想了解如何去做。 –

+0

我的問題的目的是讓你考慮一下。爲什麼不直接'長度>> = 1'? –

回答

13

32.32f的二進制數是01000010000000010100011110101110

後移:00100001000000001010001111010111

你可以看到如何浮點數從Wikipedia存儲。

符號:0

EXP:01000010 = 66

尾數:00000001010001111010111 = 2 -7(周圍)

所以結果= 2 (66-127) *( 1 + 2 -7)= 2 -59(約)

這不是零。如果你使用printf("%.40f\n",x2);那麼你會看到它。

如果你覺得奇怪爲什麼這些魔法數字有效:你可以仔細閱讀wiki頁面或者閱讀這個paper