ActionScript 3.0で始めるオブジェクト指向スクリプティング

第60回 【特別編】1/0で考えよう − ビット演算

この記事を読むのに必要な時間:およそ 4 分

技術評論社より発売された拙著ActionScript 3.0パフォーマンスチューニングから,ActionScript 3.0の最適化の仕方をご紹介する特別編は今回で終わりとなる。結びとして,数値演算のうち2進法の計算を解説したい。コンピュータは内部的に2進数で演算している。そのため,数値を2進数で扱えばコンピュータにより近い計算になり,お得なことが少なくない。他方で,考え方を正しく理解しないと,サンプルだけ見ても使いこなすのは難しい。

2進数とは

まずは,2進数を数学的に式で表そう。といっても,さほど難しいことはない。小学校の算数で,数は10の束ができると1繰り上がると習った。これが10進法だ。たとえば,10進数の123はつぎの式で表せる。

123=1×100+2×10+3×1=1×102+2×101+3×100

2進法は2の束で繰り上げればよい。たとえば,2進数の1011は,同じように式で表せば,10進数の11だとわかる。

1011(2進数)=1×23+0×22+1×21+1×20=8+0+2+1=11(10進数)

もっと一般的に,k桁目の数をnkとすると,10進数と2進数はそれぞれつぎのように表される。

10進数
nk×10k-1+...+n2×101+n1×100
2進数
nk×2k-1+...+n2×21+n1×20

2進法では少し数が大きくなると,桁数がたちまち増える。人間の目には煩わしい。しかし,数字は1と0しかないので,四則演算もふたつの数字の4つの組合わせさえ考えれば足りる。単純な演算を大量に扱うのは,コンピュータのもっとも得意とするところだ。この2進数の演算をどのような場合にどう用いればよいのかご説明したい。

ActionScript 3.0定義済みクラスで使われている2進数の考え方

ActionScript 3.0定義済みクラスで2進数の考え方が使われている例をひとつ紹介しよう。それは,Arrayクラスだ。第24回「インスタンスの管理と配列の並べ替え」インスタンスの重ね順を管理するで,Array.sort()メソッドに渡せるArrayクラスの定数を掲げた第24回表2再掲)⁠

表2 Array.sort()メソッドに指定できるArrayクラスの定数(再掲)

定数説明
CASEINSENSITIVE英字の大文字小文字を区別せずに並べ替える。
DESCENDING並べ替えの順序を,降順(大きい順)に指定する。
NUMERICエレメントが数値の配列を,その値の大きさで順序づける。
RETURNINDEXEDARRAYターゲットの配列は変更せず,並べ替えた結果の整数インデックスをエレメントとした配列が返される。
UNIQUESORTエレメントに重複がない配列のみを並べ替える。重複があれば,0を返す。

これらの定数には整数値が与えられている。たとえば,定数Array.NUMERICの数値は16で,Array.DESCENDINGは2だ。すると,これらふたつの合計値Array.NUMERIC+Array.DESCENDING(18)Array.sort()メソッドの引数に渡すと,配列エレメントが数値の大きい順に並べ替えられる。

var my_array:Array = [30, 0, 1000, 4, 200];
my_array.sort(Array.NUMERIC + Array.DESCENDING);
trace(my_array);   // 出力: 1000,200,30,4,0

こういう結果が得られるのは,18という値は定数Array.NUMERICArray.DESCENDINGの組合わせ以外ありえないからだ。さらにいえば,これらArray定数のどの組合わせの合計をとっても一意,つまり他の組合わせの合計にはならない。Array定数値はそのように定められている。

種明かしは簡単で,定数値を2進数で見ればよい表1)⁠各定数値は,先頭が1で後は0の2進数だ。そしてみな桁数が異なる。すると,10進数の18は2進数では10010となり,1の桁がふたつあることからふたつの定数の組合わせになる。そして,1の桁の位でふたつがどの定数かもわかる。

表1 Arrayクラスの定数と与えられた整数値

Arrayクラスの定数ソートの指定与えられた10進数2進数表現
CASEINSENSITIVE大文字小文字を区別しない1=201
DESCENDING降順値(大きい順)の並べ替え2=2110
UNIQUESORT重複のない並べ替え4=22100
RETURNINDEXEDARRAY並べ替えたインデックスの配列を返す8=231000
NUMERIC数値の大きさで並べ替え16=2410000

ビット単位の論理和演算

[ヘルプ]Array.sort()メソッドを調べると,引数に定数を「複数指定する場合は,ビット単位の論理和(OR)|演算子で区切」るとしている。使うのは加算演算子+ではないというのだ。しかし,少なくともArray定数については,結果はビット単位の論理和Iでも加算+でも変わらない。異なるのは演算の対象となる桁同士が,どちらも1のときだ※1)⁠

1+1=10(2進数)
1|1=1(2進数)

加算の場合にはひと桁繰り上がる。だが,⁠ビット単位の演算」では,計算した桁同士の結果が他の桁に影響を及ぼすことはない。つまり,繰り上がりや繰り下がりは起こらない表2)⁠もっとも,Array定数についていえば,そもそも1のある桁はすべての定数で異なるように定められている。だから繰り上がりはなく,加算でも結果は変わらない。

表2 ビット単位の論理和演算子|の演算結果

ビット単位の論理和演算結果の2進数
0|0
0
0|1
1|0
1
1|1
1

とはいえ,繰り上がり・繰り下がりのない計算とある計算でどちらが楽かを考えれば,ビット演算に軍配は上がる。したがって,最適化を目指すなら,ビット単位の演算をできるだけ使った方がよい。ちなみに,⁠ビット」というのは2進数のひと桁を示す。ビット単位の演算というのは,2進数を桁ごとに計算するということだ。

前述のとおり,2進法の演算は1と0の4とおりの組合わせしかないので,結果については問題なかろう(前掲表2)⁠しかし,2進数とその計算をどういうときに用いるのか,具体的な例が思い浮かばないかもしれない。そこで,ごく簡単なゲームの中で,2進数とビット単位の演算を使ってみよう。

※1
論理演算子にも論理和||がある。ビット単位の論理和演算子|も考え方は同じで,どちらか一方でも1trueなら,演算結果は1trueになる。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入