32ビットの数値を3で割るための(比較的)よく知られたハックがあります。実際の高価な分割を使用する代わりに、数字にマジックナンバー0x55555556
を掛けることができます。結果の上位32ビットは、私たちが探しているものです。たとえば、次のCコード:GCCと-O2
でコンパイルさ0x55555556が3ハックで分割するのはなぜですか?
int32_t div3(int32_t x)
{
return x/3;
}
、この中の結果:それは何ので
08048460 <div3>:
8048460: 8b 4c 24 04 mov ecx,DWORD PTR [esp+0x4]
8048464: ba 56 55 55 55 mov edx,0x55555556
8048469: 89 c8 mov eax,ecx
804846b: c1 f9 1f sar ecx,0x1f
804846e: f7 ea imul edx
8048470: 89 d0 mov eax,edx
8048472: 29 c8 sub eax,ecx
8048474: c3 ret
私はsub
命令を推測しているが、負の数を固定する責任があります引数が負の場合は基本的に1を加算し、そうでない場合はNOP
を加算します。
しかし、なぜがこれを行いますか?私は手作業でこのマスクの1バイト版で小さな数値を掛けようとしていましたが、パターンが見当たらず、どこにも何の説明も見つけられません。それは0x5f3759dfのように、その起源が誰にも明らかではない謎の魔法のようです。
誰かがこれの背後にある算術の説明を提供できますか?
[分母が分かっている場合は高速整数分割が可能ですか?](http://stackoverflow.com/questions/2616072/faster-integer-division-when-denominator-is-known) –
@PeterO。私が上で概説した特定のアルゴリズムがその質問(または答え)のどこに説明されているかを教えてください。 – szczurcio