10
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.0

最終結果は次のようになります。

このアイデアはhttp://en.wikipedia.org/wiki/Fast_inverse_square_rootからのものです。float の long が取り出され、ビットごとの操作が実行されるコードのセクションを理解しようとしています。ポイントは、分岐を回避してパフォーマンスを向上させることだと思いますか?

上記のコードは失敗します。誰かが私が間違っていることを教えてもらえますか? longストレージを取得して操作するのと同じくらい簡単だという印象を受けましたが、floatこれは間違っていますか?

コードを次のように変更すると、興味深いことがわかりました。

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

この番号 (0x5f3759df) をミックスに追加します。

length*100 を出力すると : 17.0538 // 16.16 の近似値
を異なる長さで試しても同じ結果が得られます。

例: 長さ = 100; 結果は : 10.3299?? // ほとんど...

4

1 に答える 1

16

32.32f のバイナリは01000010000000010100011110101110.

シフト後:00100001000000001010001111010111

ウィキペディアから浮動小数点数がどのように格納されているかを確認できます。

符号:0

exp:01000010=66

仮数部:00000001010001111010111=2 -7 (前後)

したがって、結果 = 2 (66-127) *(1+2 -7 )=2 -59 (約)

ゼロではありません。使えばprintf("%.40f\n",x2);わかります。

マジック ナンバーが機能する理由に違和感を感じた場合は、wiki ページを注意深く読むか、この論文をお読みください。

于 2013-06-04T00:59:11.250 に答える