馬鹿全さんが FLASHer 向けビット演算入門記事をアップしてますね。AS3 においては、必ずしも高速化にはつながらないですが、ビット演算ってパズルみたいで面白いですよね。例えば、
n = Math.max(n, 255);
※ n は整数 (uint)
の代わりに、
n = (n | (((n & 0xffffff00) + 0x7fffffff) >> 31)) & 0xff;
とか!
何をやってるのか少しずつ見て行ってみましょう。
一番最初に実行されるのは n & 0xffffff00 です。これで、「n が 255 以下の場合には 0 、それ以外は 1 以上」な値が作れます。
なぜかというと、255 以下の値というのは、8 ビットで全て表現出来るため、上位 24 ビットは必ず全て 0 になります。逆に 255 より大きい値は 9 ビット以上必要で、必ず上位 24 ビットのうち最低でもひとつは 1 のビットがあります。ここで、0xffffff00 (2 進数で書くと
1111 1111 1111 1111 1111 1111 0000 0000
となる) との論理積をとると、その上位 24 ビットの値のみが反映され、255 以下の場合は 0、255 より大きい場合は 1 以上となります。
例えば 57 は
0000 0000 0000 0000 0000 0000 0011 1001 ← 57 &) 1111 1111 1111 1111 1111 1111 0000 0000 ← 0xffffff00 ------------------------------------------ 0000 0000 0000 0000 0000 0000 0000 0000
で 0 となり、308 は
0000 0000 0000 0000 0000 0001 0011 0100 ← 308 &) 1111 1111 1111 1111 1111 1111 0000 0000 ← 0xffffff00 ------------------------------------------ 0000 0000 0000 0000 0000 0001 0000 0000
で、1 以上の値となります。
続いて、+ 0x7fffffff です。0x7fffffff は、
0111 1111 1111 1111 1111 1111 1111 1111
というように、最上位ビットのみ 0 な値で、ここに 1 以上の値を足せば、繰り上がりによって、最上位ビットを 1 にすることができます。前の段階で 255 以下で 0、255 より大きいと 1 以上な値を作ったので、これにより、255 以下であれば最上ビットが 0、255 より大きいと最上位ビットが 1 な値を作ることができます。
57 の例の続きで言うと、
0000 0000 0000 0000 0000 0000 0000 0000 ← 前段階で作った値 +) 0111 1111 1111 1111 1111 1111 1111 1111 ← 0x7fffffff ------------------------------------------ 0111 1111 1111 1111 1111 1111 1111 1111
で最上位ビットが 0、308 の例の続きだと
0000 0000 0000 0000 0000 0001 0000 0000 ← 前段階で作った値 +) 0111 1111 1111 1111 1111 1111 1111 1111 ← 0x7fffffff ------------------------------------------ 1000 0000 0000 0000 0000 0000 1111 1111
で、最上位ビットが 1 になります。
続いて、>> 31 による符号付き右ビットシフトです。符号付きビットシフトというのは便利で、ビットシフトしたビット数だけ、上位ビットが、最上位ビットの値で埋められる性質があります。これを利用して、31 ビット右にシフトすると、全ビットを最上位ビットの値に変えることができます。
57 の例の続きで言うと、
0111 1111 1111 1111 1111 1111 1111 1111 ← 前段階で作った値 >> 32) ------------------------------------------ 0000 0000 0000 0000 0000 0000 0000 0000
で、全ビットが 0、308 の例の続きだと
1000 0000 0000 0000 0000 0000 1111 1111 ← 前段階で作った値 >> 32) ------------------------------------------ 1111 1111 1111 1111 1111 1111 1111 1111
で、全ビットが 1 になります。
さて、長々とやってきましたが、これで何が出来たかおさらいすると、n が 255 以下の場合は全ビットが 0、n が 255 より大きい場合は全ビットが 1 な値が作れたということです。ここまでくれば後もう一歩です。
次に、その値と、n の論理和をとります。すると、n が 255 以下の場合は n、n が 255 より大きい場合は 0xffffffff (全ビットが 1) になります。
57 の例の続きで言うと、
0000 0000 0000 0000 0000 0000 0000 0000 ← 前段階で作った値 |) 0000 0000 0000 0000 0000 0000 0011 1001 ← n つまり 57 ------------------------------------------ 0000 0000 0000 0000 0000 0000 0011 1001
で 57 のまま、308 の例の続きで言うと
1111 1111 1111 1111 1111 1111 1111 1111 ← 前段階で作った値 |) 0000 0000 0000 0000 0000 0001 0011 0100 ← n つまり 308 ------------------------------------------ 1111 1111 1111 1111 1111 1111 1111 1111
で 0xffffffff (全ビットが 1) になります。
最後に、0xff との論理積をとると、57 の例の場合は
0000 0000 0000 0000 0000 0000 0011 1001 ← 前段階で作った値 |) 0000 0000 0000 0000 0000 0000 1111 1111 ← 0xff ------------------------------------------ 0000 0000 0000 0000 0000 0000 0011 1001 ← 57
で、変わらず 57、しかし 308 の例の場合は
1111 1111 1111 1111 1111 1111 1111 1111 ← 前段階で作った値 |) 0000 0000 0000 0000 0000 0000 1111 1111 ← 0xff ------------------------------------------ 0000 0000 0000 0000 0000 0000 1111 1111 ← 255
で、255 に収まります。めでたしめでたし!
…なんか、解説しようと思ったら思ったより言葉で説明するの大変でした。ぜひ他の値だとどうなるか手を動かして試してみてください。
サイト内関連記事
この記事へのトラックバック
TrackBack URL:
http://www.be-interactive.org/trackback.php?id=519
