サイトトップ

Director Flash 書籍 業務内容 プロフィール

Adobe Flash非公式テクニカルノート

複数のフラグをひとつの整数で表す

ID: FN0806001 Product: Flash Platform: All Version: 8 and above/ActionScript 3.0/2.0/1.0

状態や設定を保持するための変数は、「フラグ」と呼ばれます。多くの場合はtrueかfalseかのブール(論理)値で、整数値が使われることもあります。このようなフラグが複数あるとき、それをひとつの値で示すテクニックをご紹介しましょう。


1. 整数の位取りを使う
たとえば、BitmapData.perlinNoise()メソッド[*1]の第7引数には、赤(R)、緑(G)、青(B)、アルファ(A)の各チャネルをそれぞれ使うかどうかについて、正の整数ひとつで指定することになっています。つまり、RGBAのチャネルそれぞれについて、使うか使わないかのフラグを4つ合わせてひとつの整数にしているのです。この値がどう決められているかをご説明します。

各チャネルには使うか使わないかのふたつの設定があり、それがRGBAの4チャネルあるのですから、組合わせは16(= 24)とおりあります。考え方として簡単なのは、その16の組合わせに整数のとおし番号をつけることでしょう。ただそれですと、ある番号がどの組合わせに当たるのかは、いちいちコード表を見ないとわかりません。

数字から組合わせがわかるようにするには、各チャンネルで使う位取りを変えればよいでしょう。チャンネルを使う場合が1、使わないときは0として、RGBAの順に1の位、10の位、100の位、1000の位を使う訳です。たとえば、11がRG、1100はBA、1111ならRGBAすべてを使うことになります。しかし、これではたった16の組合わせを示すのに1000以上の整数まで用い、途中に使われていない数値が数多く含まれてしまいます。

1000の位 100の位 10の位 1の位
アルファ(A) 青(B) 緑(G) 赤(R)

少し発想を変えれば、この問題は解決します。数字を0と1しか使わないのですから、10進法でなく2進法だとみなせばよいのです。すると先ほどの例を2進数と見たとき10進数に戻した値は、RGの11は3(= 21×1+20×1)、BAの1100は12(= 23×1+22×1)、RGBAの1111は15(= 23×1+22×1+21×1+20×1)ということになります。実は、これが初めに例として挙げたBitmapData.perlinNoise()メソッドの第7引数値の決め方なのです。

[*1] ActionScript 2.0のメソッドについては、「BitmapData.perlinNoise()メソッド」をご参照ください。


2. 合成値の計算方法
RGBAの各チャネルを使うか使わないかの1か0の値が、変数nR、nG、nB、nAに入っているとします。すると、それらを合成した0から15までの整数nColorの値は、数学的にはつぎのように求められます。

nColor = 23×nA+22×nB+21×nG+20×nR

ActionScriptでnColorの値を求める際も、べき乗のメソッドMath.pow()を使って、同じように計算してもとくに問題はありません。ただ、プログラミングでは、もう少し違った計算方法を使うこともあります。たとえば、つぎのような演算です。

nColor = nA << 3 | nB << 2 | nG << 1 | nR;

まず、ビット単位の左シフト演算子<<は、数値を2進数として桁を左にシフト、つまり位取りを上げます。左に1シフト(<< 1)するというのは、2を掛けることに等しいです。したがって、<< nというのは、2nを乗じる結果になります。

つぎに、ビット単位の論理和演算子|も、やはり2進法でふたつの数値を各桁ごとに計算します。よって、演算対象の数値は0か1のみです。そして、ふたつの数値のいずれかひとつでも1であれば、演算結果は1です[*2]。しかし、1 | 1が1になること以外は、普通の加算+と同じです。そして、今回のフラグのようにわざわざ位取りを分けている場合には、ふたつの対象数値がともに1になることはありません(逆にいえば、数値の1が重ならないように桁をずらしているのです)。

ですから、結局演算の結果は、前に示した2のべき乗との掛け算を足し合わせる数学的な式と同じになります。ただ、数値を2進数として扱うビット演算は、コンピュータのデジタル(1/0)のロジックに、より近いといえます。したがって、大量の演算をする場合には、有利なようです[*3]

[*2] 条件に指定する論理式で使われる論理和演算子||が、どちらか一方でもtrueであればtrueを返すのと同じロジックです。

[*3] ConquestArrow.addEventListener();「ActionScript3 最適化・高速化Tips 簡易まとめ」およびそこに引用されているpolygonal labs「Bitwise gems - fast integer math」をご参照ください。


3. RGBカラー値の計算
2で紹介した2進数による演算は、RGB(A)のカラー値計算にも使われることがあります。カラー値の場合には、各チャネルの値は0からFFまでの256階調です。0からFを2進数で扱えば0から1111までの4桁になり、FFまでなら8桁で表されます。したがって、nR、nG、nBのそれぞれに0からFFまでの256階調の値が入っているとすれば、これらを合成したRGBカラー値nColorはつぎのように計算できます。

nColor = nR << 16 | nG << 8 | nB;

作成者: 野中文雄
作成日: 2008年6月7日


Copyright © 2001-2008 Fumio Nonaka.  All rights reserved.