プチコン3号&BIGまとめWiki

プチコン3号&BIG 非公式初心者講座 : 第17章 ビット演算の実習

パンくずリスト

プログラマーからひとこと

ふたたびビット演算の話です。

「もういいよ! あんまり使う場面ないし!」と思うかもしれませんが、うん、まあ、いままであんまり使う場面ありませんでしたね。
そこで今回は、もっと役立つビット演算の使い方をいくつかおぼえてみよう、という回です。

これで意外と役に立つものなんですよ。
例によって、これさえおぼえておけば、人のプログラムを読むときにグンと読みやすさがアップしますし。

難しいようで、わかってみるとカンタンなことでもあるので、ANDやORの計算に慣れながら読んでいってみてください。

ループする数

インテリくん

前回までのサンプルプログラムで、ビット演算が出てきたのはおぼえてるかな?

神崎

たしか、A=(A+1) AND 3ってカタチだったよね。

インテリくん

そうそう。コレでどういう効果が出るかは、おぼえてる?

神崎

この行を通るたびに変数の数がから1ずつ増えるんだけど、まで増えたときにはに戻されるんだった、かな?

インテリくん

そういうコトだね。では、このビット演算を……

ワンパクくん

テメエら、リズムだけでサクサクおさらいするのもイイカゲンにしやがれ! このオレもついてこれてねェぞ!

インテリくん

ヒドいなあ。じゃあ、いまのAND 3がうまく動くしくみを見直してみることから始めるかい。

ワンパクくん

復習ってのもおベンキョウくさくってあんまり好きじゃねェが……
まず、サイショに変数だったトキはどうなるんだ?

神崎

A=(A+1) AND 3ってことは、言いかえると1 AND 3の計算になるよね。

インテリくん

それを2進数の式にすると、こうなるね。

01
AND11
=01

ANDを使った計算はまだ忘れてないかな?

ワンパクくん

上からメセンがニクニクしいぜ! 同じ位をクラベて、両方なら答もが片方でもあったらになるってヤツだろ。

インテリくん

そこまでワカッてるなら一気にいこうか。変数に入る数字がからまでのパターンを並べてみるよ。
それぞれ+1されるから、1 AND 3 ~ 4 AND 3の式になるね。

011011100
AND11AND11AND11AND011
=01=10=11=000

4 AND 3のときだけ、結果がゼロになるのがわかるだろう。

ワンパクくん

ホントだな。
ギャクに~までは、AND 3されても、そのままナニゴトもなく変化しねェのがフシギだぜ。

神崎

そうか、11みたいに全部で並んだ数でANDすると、数はなにも変わらないでそのまま出てくるんだね。

インテリくん

おっ、いいトコロに目をつけたね。そのとおりで、たとえばAND 2だと、そうウマくはいかないんだ。

011011100
AND10AND10AND10AND010
=00=10=10=000
ワンパクくん

タシカになんだか、スッキリしねえケッカになるな。

インテリくん

これがAND 7だとどうかな? を2進数になおすと111で、が並ぶ数字だね。

0010101111000
AND111AND111AND111AND0111
=001=010=111=0000
神崎

やっぱり3ケタまではゼッタイ変化しないで、上の数が4ケタになったとたんにゼロになるよ!

ワンパクくん

……ANDが並ぶ数を使うと、ある数まではフツウに増えて、ある数まで増えたらゼロにリセットされるってコトなのか?

インテリくん

悪くないリカイだよ。
A=(A+1) AND 7が「8回ループするたびに1回だけゼロになる」ものと考えると、IF A==FALSE THENとすれば8回に1度だけトクベツなコトができるね。

神崎

かならず8回目にゼロに戻ってくるのもベンリかもね。ON A GOTOを使ったプログラムでも、自動的にループになるよ。

ワンパクくん

タシカにサンプルプログラムでやったコトも同じか……。
で、111みたくが並ぶ数ってのはナニとナニがあるんだ? はワカッたが、いちいち探すのはメンドくせェぜ!

インテリくん

だいじょうぶ、それにはパターンがあるんだ。先にそういう数を見せた方が早いかな?
2進数にするとの連続になる数字

10進数2進数
1
311
7111
151111
3111111
63111111
1271111111
25511111111
神崎

1、3、7、15、31……うーん、パターンがあるような、ないような……

ワンパクくん

ナンだか数字パズルみたいになってきたな。ニガテなテンカイだぜ!

インテリくん

ゼロから数え始めるコンピューターのクセに合わせて、数を1ずつ増やすとどうかな?

神崎

ん? 2、4、8、16、32……あっ! ぜんぶ倍になってるよ!

インテリくん

2の倍は4、4の倍は8、8の倍は16……いわゆる「2のべき乗」だね。2のべき乗マイナス1と考えれば、アンガイおぼえやすいだろう。「64」や「256」なんかはゲームでも見たことある数じゃないかな?

ハカセ

64分の1の確率でアイテムをドロップ、とかアリガチじゃな。
コンピューターとアイショウのいい数じゃからのう。ムカシはバキ●ラを256回撃つと倒せるというウワサが……

ワンパクくん

ケッ、ムカシ話にはキョウミがねえぜ!

ハカセ(泣)

ま、まあそれもこれもビットの考えカタにそっとるのじゃよ。

インテリくん

この数だと「63」にWAIT命令を組みあわせると、こんな風にもできるね。

  1. @LOOP
  2. WAIT(1)
  3. A=(A+1) AND 63
  4. PRINT A
  5. GOTO @LOOP
ワンパクくん

WAIT(1)は60分の1秒だけ待つってコトだろ。それとコレとどうカンケイが……

神崎

ビット演算では64回に1回リセットだから……1秒と4/60秒だけループした時に、変数がゼロにリセットされることになるね。

インテリくん

つまり「だいたい1秒」でリセットされるカウンターだね。ここではただのPRINTだけど、ゲームのタイマーや1秒ごとにたまるダメージとか、使いどころはあるんじゃないかな。

ワンパクくん

オイオイ、「だいたい1秒」って、そんなテキトウでいいのか!?

ハカセ

目に見えるワケではないからのう、体感時間としてはアリじゃ。ぶっちゃけプログラムにはよくある手じゃよ。
その後、プログラムを解析されて「なんちゃって1秒」だとバレるところまでふくめてワンセットじゃ。

ワンパクくん

は、はかりしれねえセカイだぜェ……。

BUTTON()命令の種明かし

ワンパクくん

ン? さっきの「2、4、8、16、32……」って数、マエにも見た気がするな……

神崎

そういえば、BUTTON()命令に使われてる数字がそうだったよ!

十字ボタン↑1Aボタン16Lボタン256
十字ボタン↓2Bボタン32Rボタン512
十字ボタン←4Xボタン64
十字ボタン→8Yボタン128
インテリくん

ソレもビット演算の考え方を使ってるんだけど、しくみは飛ばしておぼえていたね。ためしに2進数に直してみるよ。

10進数2進数
1
210
4100
81000
1610000
32100000
ワンパクくん

そうか、2進数にするとキリがいい数だったんだな。ソコまではワカったが……コレとビット演算がカンケイあんのか?

インテリくん

これだけだと、まだわかりづらいね。2進数のケタをそろえてみよう。

10進数2進数
1000001
2000010
4000100
8001000
16010000
32100000

先頭にゼロをつけただけで、数が変わったわけじゃないよ。

神崎

ははあ、右からジュンバンに1ケタずつ、ボタンとのペアができてるんだね。こうやって見ると数字っていうよりは、記号みたいだよ。

インテリくん

タシカに。それぞれのケタがスイッチで、が「オフ」でが「オン」だって考え方があるんだ。
だから、こういう表でもになっているケタを「ビットが立っている」と言ったりするね。

神崎

からになるのが、「ビットが立つ」ってことか。

インテリくん

000010なら第1ビットが立っている、なんて言うね。1ケタ目が第0ビット、2ケタ目なら第1ビットさ。

ワンパクくん

またゼロから始める数えカタかよ……ギョウカイ用語はいいから、サッサとハナシをススメやがれ!

インテリくん

じゃあ、たとえば「十字ボタン↑」と「Aボタン」が同時押しされた時で考えてみよう。
10進数なら1617が変数に入るけど、この数を2進数にするとどう見えるかな?

神崎

えーと、こうなるかな。

10進数2進数
1000001
16010000
1+16=17010001
ワンパクくん

お、オォ? そのまま組み合わさったみてェな数になったぜ!

インテリくん

こういう「1、2、4、8、……」と倍々になっている数のトクチョウだね。数をたすとビットが立ったままキレイに合わさるんだ。

神崎

ますます記号みたいだね。 つまりBUTTON()命令だと、第0ビットが「十字ボタン↑」のスイッチになっていて、第4ビットは「Aボタン」のスイッチってことだね。

十字ボタン↑10000000001
十字ボタン↓20000000010
十字ボタン←40000000100
十字ボタン→80000001000
Aボタン160000010000
Bボタン320000100000
Xボタン640001000000
Yボタン1280010000000
Lボタン2560100000000
Rボタン5121000000000
ワンパクくん

ナカナカおもしれえハナシだが……だからナンのイミがあるんだって気もするぜ!

インテリくん

ここからがベンリなところだよ。
BUTTON()命令で言えば、Aボタンが押されているかをチェックしたい時はどうするんだったかな?

ワンパクくん

何もカンガエずに、IF文でAND 16と書けばイイって、教わったな。

  1. @LOOP
  2. B=BUTTON()
  3. IF B AND 16 THEN PRINT”Aがおされてます”
  4. GOTO @LOOP
インテリくん

じゃあ、今度はちゃんと見てみよう。
いま出てきた「十字ボタン↑」と「Aボタン」が同時押しされた時の数「010001」に、AND 16のビット演算をしてみるね。

010001
AND010000
=010000
神崎

あっ! Aボタンのスイッチになってる第4ビットだけが立ってるよ!

インテリくん

わかってきたかな。チェックしたいケタに1を、それ以外のケタに0を入れてANDで演算すれば、そのビットが立っているかどうかスグにわかるんだ。
このトクチョウをうまく使ったのが、BUTTON()命令とANDを使ったIF文だね。

ワンパクくん

ゴクリ……てことは、第5ビットのBボタンが押されてるかどうかで考えると……

010001
AND100000
=000000

ヤッパリ答はゼロ、第5ビットは立ってねえってコトがワカるぜ!

インテリくん

「1、2、4、8、……」という数で組み立てておくと、こういうチェックにベンリなのがわかるね。
頭で考えるよりも、こういう数のパターンをひとつおぼえておくといいよ!

ビット演算を使ったフラグ

ワンパクくん

フーム……このパターンをBUTTON()命令イガイに使うとすると、トウゼン変数だよな。フラグなんかにベンリそうな気はするぜ!
どうするのがイイのかはサッパリ思いつかねェけど。

インテリくん

スッキリあきらめたね。
まあ、さっきのBUTTON()命令だって、「上ボタンを押すと第0ビットのフラグが立つ」と考えればリッパにフラグさ。その応用で作ればいいよ。

ワンパクくん

ナルホド、そういうミカタもあるか……。

神崎

さすがにBUTTON()なみに10ケタいるとは思えないけど、4ケタあれば、4つのオン・オフをいちどに見られるフラグになるワケだね。

ワンパクくん

イヤちょっと待てよ! BUTTON()ならボタンを押せばカッテにフラグが立ってくれたがよォ、自分のプログラムの中でフラグを立てたり消したりするのは、どうやりゃいいんだ?

神崎

たしかに、10進数みたくA=A+1みたいに書くわけにはいかないよね。第2ビットをにするには、ええと……

インテリくん

フラグを立てるならビット演算のORを使うのがキホンかな。
たとえばまっさらな変数があったとしよう。A=0だから、2進数でも0000なのはわかるよね。
この3ケタ目(第2ビット)を立てるには、こうするよ。

0000
OR0100
=0100

ここでORに使った0100は、10進数で言いかえれば4。
つまり、A=A OR 4と書けば、第2ビットが立つことになるね。

ワンパクくん

ORを使うのはワカッたが、イチイチ10進数に直すのがカッタルイぜ!

ハカセ

なれないウチは並んだ2進数の右ハジから、「1、2、4、8、……」と倍にしながら数えていくのがカンタンかもしれんな。10進数で右ハジから「一、十、百、千、万、……」とケタを数えるノリでいけるぞい。

神崎

第2ビットが立っているときに、もういちどOR 4すると……

0100
OR0100
=0100

やっぱりそのままだね。ORはビットを立てるために使うってコトか。

インテリくん

オン・オフを逆にしたい時は、XORがオススメだね。
ためしに11001000、どっちにも0100XORしてみるよ。

11001000
XOR0100XOR0100
=1000=1100

XORした第2ビットだけがひっくり返って、ホカのケタはそのまま残るのがわかるだろう。

神崎

XORって使い方がムズカシいと思ってたけど、こういう時にベンリなんだね。

ワンパクくん

じゃあ、とにかくにしたいってトキは……そうか、ANDだな?

01001111
AND1011AND1011
=0000=1011

1011AND、10進数で言えばAND 11だな。 これでホカのケタはそのままで、第2ビットだけがになったぜ!

ハカセ

なかなかワカッてきたではないか。
さっきの復習じゃが、ANDを使ったフラグチェックには、こういうテクニックもあるのう。

1110
AND0100
=0100

AND 4すると、第2ビット以外はゼロになったじゃろう。

ワンパクくん

BUTTON()で使ったテクだな! 第2ビット以外をゼロにすれば、第2ビットのオン・オフだけがハッキリする。ツマリ……エー……

神崎

そうか! そうなると、IF A THENの形が使えるんだね。

インテリくん

そのトオリ。1行にまとめると、IF A AND 4 THEN~だね。
もちろんホカにもA=A AND 4:IF A==FALSE THEN~ なんかでもいいけど、とにかく決まったケタのナカミだけがスグにわかるよね。

ワンパクくん

ホカのケタがまるまるゼロになっちまうが……、ああ、そこは変数のナカミをあらかじめコピーしとけばいいのか?

ハカセ

そうじゃな、A=Bとか逃がしてから、B=B AND 4などとするのがアンゼンじゃろうの。

インテリくん

まだまだイロイロなテクニックはあるよ。なかなかオクの深い世界だろう。

ワンパクくん

とっつきはワルいが、使いミチはワカッてきた気がするぜ。てコトは、このアトすぐに使う場面があるワケだな?

ハカセ

いや、そうともかぎらんが。

神崎

えー……?

今回のまとめ

ループする数
  1. A=(A+1) AND 3
こう書くと、A=0から始めて、この式を3+1回くり返したとき、変数に戻ります。
3以外に、7、15、31、63……と、「2のべき乗」マイナス1の数で同じパターンが使えます。
ビット演算を使ったフラグ
たとえば2進数の0000(10進数の)を「4つ並んだフラグ」と見なせば、4種類のオン・オフを管理できます。
0001(10進数の)なら「第0ビットが立った」状態、0100(10進数の)なら「第2ビットが立った」状態と言えます。
他のケタを変化させずに第2ビットだけをにしたければOR 4(2進数の0100)、第2ビットだけをにしたければAND 11(2進数の1011)することになるでしょう。
第2ビットの状態だけを反転させるには、XOR 4(2進数の0100)がいいでしょう。
わざとAND 4(2進数の0100)することで、第2ビット以外をにして、第2ビットの状態をハッキリさせる方法もあります。
こういったあるひとケタだけがになっている数は、10進数に直せば「1、2、4、8……」と倍々に増えていく数になります。

メニュー 【3号】

ヘルプ

リンク

最近の更新

最近の人気ページ

オンライン情報

  • 現在同時に 1 人がこのサイトを見ています
  • このページはこれまでに 957 回、本日は 1 回、昨日は 0 回閲覧されました

ページの先頭に戻る

表示モード : [ スマホ・3DS対応表示 | クラシック表示 ]
PukiWiki 1.4.7 Copyright © 2001-2006 PukiWiki Developers Team. License is GPL. Based on "PukiWiki" 1.3 by yu-ji
ページの処理時間 : 0.356 秒 | このページの最終更新 : 2022/09/20 (火) 12:49:13 (565d) | ログイン
Copyright(C) 2011-2014 プチコンまとめWiki ◆1sxkymI8ji30