この章では、「ビット演算 (えんざん)」というものをおぼえます。
前にちらっと出てきましたね。
その時は、むずかしいので説明はしませんでした。
そうです、ビット演算はむずかしいのです。
あんまりむずかしいので、飛ばして読んでもいいです。ほら、ここにボタンも用意しましたよ。【とばし読み】
これまでもむずかしい話はいろいろしました。どれもむずかしいかわりに、かならず必要なものでしたから、それはいいと思うんです。
配列変数なんて、かなりめんどくさかったですが、ないと困るものでしたよね。
ところがビット演算は使わないでも、まあなんとかなるんです。
私もはじめにおぼえたときは、「なくていいじゃん」と思いました。
どうです、とばし読みしたくなってきたでしょう。
じゃあ何のためにおぼえるの? いくつか理由はあります。
1.コンピューターの考え方がわかる
私たちがものを考えるとき、だいたいイメージとか日本語でものを考えるように、コンピューターは「ビット」でものを考えます。
つまり、ビットの考え方を理解すると、ぐっとコンピューターの考え方に近づけると言えるでしょう。
こう言われてヤル気が出てきた人は、わりとプログラマー向きな性格だと思います。
ぶっちゃけ、コンピューターの考え方がわかってもモテませんよ。そんなに役に立たないですよ。
2.短いプログラムが書ける
ビット演算をうまく使うと、IF文を何行も使うようなプログラムも1行でぐっとシンプルに書けるようになります。
これはアツいですね。と、私は思いますが、それは私がプログラマーだからかもしれません。
プログラマー的にはシンプルにスパッと書けるとプロっぽくてうれしいものですが、でもちょっとくらいプログラム長くたって別にいいじゃん、と言われると、まあ、それもそうだな、なんて気もします。
3.速いプログラムが書ける
コンピューターは「ビット」でものを考える、とさっき書きました。
ビット演算はビットを使ったプログラムなので、コンピューター的にはラクっていうか、やりやすいものみたいです。
おおざっぱに言って、ビット演算を使ったプログラムと、同じことをビット演算を使わずにやったプログラムでは、ビット演算した方が速くなります。
よくゲームで「処理落ち」とか「重い」とか言うでしょ。アレが少なくなります。
もっとも、この講座で教えているレベルだと、違いがまったくわからないていどの速さだったりもします。高レベルなプログラムになるほど必要になってくるんですが、いま必要かっていうと別にそうでもないんですね。
4.人のプログラムが読みやすくなる
けっきょく一番だいじなのは、ここかもしれません。
ビット演算を使ってるプログラムは、ビット演算の考え方を知らないと、何が書いてあるのかよくわかりません。
そして参考にしたいプログラムにかぎって、ビット演算を使ってるのです。これはプログラムあるあるです。
おおむねすぐれたプログラマーというのは、コンピューターが好きで、短くて速く動くプログラムを書きたがるものです。つまりビット演算をしたがるものなのです。
すぐれたプログラマーが書いたプログラムを読むのはとても勉強になりますが、書いてあることがわからないとあまり勉強になりません。そこでビット演算の初歩だけでもおぼえておくといい、というわけです。
どうです? ビット演算を知りたくなってきましたか?
やっぱりそうでもないですか?
その気持ちもとてもよくわかるので、ここにボタンがあるのです。【とばし読み】
まあ、今までの話をきいて、じゃあおぼえてみるか、と思った人だけが読むくらいのサジかげんでちょうどいいような気がします。
いいかげんにしろ! あれだけムズかしいとかスグには役に立たねェとか言われたアトじゃ、そうそうヤル気は起きねーぞ……
ではビット演算のキソから始めようか! ワクワクするよね!
コ……コイツ、ものすげえタフか、それともオレのハナシをきいてねェのか……。
まあ、ここはスナオに話にのっておこうか。
ビット演算をリカイするには、その前に「2進数」のことを知らないといけないね。
2進数?
ボクらがふだんイシキせずに使ってる数字は、「10進数」でできているんだ。これがコンピューターだと、2進数になるんだね。
それにしちゃ、今までBASICでフツーに数字を使ってなかったか? アレも2進数ってやつなのか?
BASICではふつう、ボクらにもわかりやすいように10進数しか出てこないんだ。ボクらの目に見えないだけで、コンピューターの中では2進数で動いているんだよ。
そうか……わざわざオボエなくていいっていうのは、そういうトコロなのかあ。10進数と2進数はどう違うの?
ボクらの10進数では、0・1・2・3・4・5・6・7・8・9の10コの数字の組み合わせで数をつくるよね。これが2進数だと、「0」と「1」の2コの数字しか使わないんだ。
エ、……ハァ!? それじゃモノを数えられねェだろ!
そうでもないんだな。
ここからは、区別しやすいよう2進数には線を引いておくよ。
たとえば10進数で「0」「1」の次は「2」だよね。
2進数だと、「0」「1」の次は「10」になるんだ。
ジ、10だと!?
2進数だと10と書いて「イチゼロ」とか読む方がいいんだけど……
うーん……急にチシキをつめこまれてる気がしないでもないぞ。
もうちょっとユックリいこうか。
10進数では、使える10コの数字の中で一番大きいのは「9」だよね。9より大きい数を書くときはどうするかな?
そりゃトウゼン、1ケタ位 (くらい) が上がって「10」だゼ! ……ン? 10?
そう、2進数も同じようなものなのさ。
ええと、2進数だと使える2コの数字の中で一番大きいのは「1」。それより大きい数を書くときは……
位が上がって、「10」になるワケか!
そういうコト。このルールだけオボエれば、2進数はカンペキさ。
ホント!? うーん、10の次は1ケタ目が上がるから、11。その次は、もう上げられる位が残ってないから、位上がりして100……。
オイオイ、とんでもねえハイペースでケタが上がってるぞ! ホントにコレで合ってるのか?
バッチリだよ! 0~10までを数えた表がコレになるね。
10進数 | 2進数 |
---|---|
0 | 0 |
1 | 1 |
2 | 10 |
3 | 11 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
こんなカンジで、どんどんケタが上がるから、1010と書いて「イチマルイチマル」とか読むんだね。
フーム……じゃあ10進数で「1976」は、2進数だとどうなるんだ?
……。
……。
プチコンに聞いてみようか!
さては、わかんネェんだな!
まあ、2進数をいちいち手で計算するのはタイヘンだからね。コンピューターに聞くのがフツウなのさ。
プチコン3号の場合、BIN$()命令で10進数を2進数の文字列に変換することができるよ。こんなカンジにね。
- PRINT BIN$(1976)
- 11110111000
- OK
「1976 = 11110111000」か……。ニンゲンサマがわからんものも、プチコンならばイッシュンなんだな、カンゼンにオレたちの敗北だぜ。
逆に、2進数を10進数に変換することはできるの?
もちろん。2進数の頭に&Bをつけると、プチコンはそれを10進数の数値に変換してあつかってくれるのさ。
- PRINT &B11110111000
- 1976
- OK
さらに、プチコンを使わずに2進数を変換する方法もあるよ。
ホウ、くわしくハナシを聞かせてもらおうじゃネェか!
それじゃあ、Google検索してみよう!
ナンだソレ! ググんのかよ!
しかも、本当にそれで答が出るんだ!
ググった答えは「1976 = 0b11110111000」か……。この「0b」ってのはナンだ?
さっきの&Bみたいに、10進数と区別するための記号だね。1976をただ2進数で言えば11110111000だけど、これだと10進数の「111億1千11万1千」にも見えるから、アタマに0bと付けるのがマナーってことかな。&Bよりも広く使われているんだ。
&Bをつけるプチコンは少数派なんだね。
BASICでは&Bがフキュウしてるんだ。いいかえると、BASIC以外ではほとんど使わないね。
だいたいわかってきたけど、それにしてもメンドくさい数え方だね……。
もともとコンピューターはスイッチがON (オン) かOFF (オフ) かの組み合わせで作られたからねえ。この2つの組み合わせを「ビット」と言うんだ。
ん……ビット?
ワスれるトコだったぜ、アブねえ! 「ビット演算」のハナシはドコ行ったんだ?
それじゃあ、プチコンで使うビット演算のサンプルを見てもらおうか。
- A=5 AND 3
- PRINT A
Aは変数だね。これをRUNすると、変数Aに1が入るよ!
ハ、ハァ!?
- RUN
- 1
- OK
ANDっていうから、てっきり5+3みたいなコトかと思ったけど……
5 AND 3はそういう計算とはちがうモノだってオボエておこうね。
答だけ見ても何だかわからないだろうから、トチュウの計算式も見てみよう!
101 | |
AND | 011 |
= | 001 |
えーと……
なんだコレ! ワカるフンイキがまったくねェぞ! 5 AND 3のドコからこの式になるってんだ!
いやいや、たぶん2進数がここで出てくるんだよね……。
そのとおり。5を2進数にすると101。3を2進数にすると011になるね。
……3を2進数にすると11じゃなかったか?
アタマにつけるゼロは、いくらつけてもいいんだ。101と位をそろえるために、1コつけておいたよ。
ウーム……つまり、5 AND 3を2進数にすると、
101 | |
AND | 011 |
ココまではまあワカッたぜ。だがコタエが001ってのは、ナットクいかねェな!
習ったことのない計算だから、そう思うのもトウゼンだね。
ビット演算の「AND」では、「両方とも1になっている位だけ1になる」とオボエると……カンタン……かなあ?
……かなあ?
ダレもナットクいってねェじゃねえか!
うーん。「位」がポイントなんだよね。たとえば1ケタ目は……
101 | |
AND | 011 |
両方とも「1」になっている位……だから……
101 | |
AND | 011 |
= | ??1 |
答も1になるってコト?
いいよ! そこまでワカれば、あともカンタンなハズ!
つまり2ケタ目も、こういうコトか?
101 | |
AND | 011 |
= | ??1 |
コレはかたっぽが「0」、もうかたっぽは「1」だから、
101 | |
AND | 011 |
= | ?01 |
ゼロがくるワケか?
そのとおり! 3ケタ目はもうわかるよね。
片方が「1」、もう片方が「0」ということは……
101 | |
AND | 011 |
= | 001 |
これで001までは答が出たね。
その001は2進数だから、10進数に直すと……
1が変数Aに入るってコトか。
計算のしかたさえワカれば、あんがいラクだろう。たとえばB=7 AND 11だとどうなるかな?
ツギツギに出してきやがって! まあヤリ方はワカッてるぜ。まず2進数に変えるんだろ?
7は111、11は1011だから、こうなるゼ!
0111 | |
AND | 1011 |
= | ???? |
で、「両方とも1になっている位」をさがすと……
0111 | |
AND | 1011 |
= | ??11 |
1ケタ目と2ケタ目が「1」になるね。のこった位はトウゼン「0」だから……
答はこうなるね。
0111 | |
AND | 1011 |
= | 0011 |
0011、つまり10進数で言いかえると3が変数Bに入ることになるね。どうだい、思ったよりはカンタンだろう?
やり方ドオリにやれば、まあデキねえコトはねェが……トンデモなくメンドくせェぜ!
ANDのほかにも、「OR」や「XOR」の計算もあるんだけど……
ウオォー! メンドくせェー!!
ワンパク君、すっかりOverflowエラーというトコロじゃな。
などとBASICネタもクールに使いこなすワシじゃ、ハカセじゃ。ビット演算の「OR」も「XOR」も「AND」とあまり変わらんぞい。ものはためしじゃ、ジッサイの計算式を見てもらおうかの。
0101 | |
OR | 0011 |
= | 0111 |
0101 | |
XOR | 0011 |
= | 0110 |
NOT | 1101 |
= | 0010 |
ゼェ、ゼェ……。アタマがワレそうだぜ……。
ひととおりオボエたけれど、けっきょくコレって何につかうの?
たしかに、何の役に立つのかわからないとハリアイがないよね。
じゃあ、ちょっと前に出てきたこのプログラムをおぼえてるかな?
- B=BUTTON(1)
- IF B AND 1 THEN BEEP 52
- IF B AND 2 THEN BEEP 53
- IF B AND 4 THEN BEEP 62
- IF B AND 8 THEN BEEP 25
たしかサンプルプログラム3で出てきたね。
BUTTON()命令とIF文の組み合わせで、十字ボタンの押された方向を調べるんだったっけ。
「IF B AND 1」と書くと、「Bの中に1がまじっている」というイミになると習ったよね。
十字ボタンの右上が押されたら、BUTTON()命令で変数Bのナカミには1(上)+8(右)の9が入る……。
で、Bのナカミが9でもなぜか「IF B AND 1」や「IF B AND 8」と書くとアタリになる、って話だったな……。
あらためて考えると、ワケがわからねェぜ!
あれ、だけどこのB AND 1って、ビット演算の書き方じゃないかな?
そのとおり! もう1度、このIF文をビット演算の考え方で見てみると、イミがわかってくると思うよ。
チクショウ、またビット演算すんのかよ!
まず右上が押されて変数Bに9が入ったとするだろ……で、56行目がIF B AND 1 THEN……。
これは変数のナカミを考えると、IF 9 AND 1 THENってコトだよな。
9 AND 1は、こう計算するんだったよね。
1001 | |
AND | 0001 |
= | 0001 |
答は0001、10進数に直すと「1」になるね。
じゃあ次の57行は……IF B AND 2 THENだから、9 AND 2をビット演算すると……
1001 | |
AND | 0010 |
= | 0000 |
オ、オォ!? キレイにゼロになったぜ。
だんだんカラクリが見えてきたね。「B AND 4」を調べる58行だと、
1001 | |
AND | 0100 |
= | 0000 |
やっぱりゼロ。
「B AND 8」を調べる59行なら、
1001 | |
AND | 1000 |
= | 1000 |
これを10進数に直すと「8」になるね。
下方向(AND 2)も左方向(AND 4)もビット演算のケッカはゼロ……。上(AND 1)や右(AND 8)だと、ゼロにはならねェんだな。
ソコだね!
ちょっと話がそれるようだけど、IF (変数) THENというカタチのIF文は、「変数がゼロじゃなければ」というイミになるんだよ。
ここと合わせて考えてみよう。
ってコトは……56行と59行のIF文の中にあるビット演算のケッカがゼロじゃないから……
……THENのサキの命令がジッコウされるってワケか!
そういうコト!
BUTTON()命令で変数に入る数字には、はじめからビット演算しやすい数字が選ばれているんだよ。
フムフム。たしかに変数Bに8(右ボタン)が入った時は、B AND 8以外ではゼロになるね。
それ以外のどの数でも、ちゃんとウマく動くようにできてるよ。なかなかベンリだろう。
ナルホド……サンプルプログラム3のころのギモンが、やっとトケたってカンジだぜ。
しかしよォ……
どうしたのワンパク君。スッキリしないカオじゃないか。
BUTTON()命令はもともとコレのために作られてるけどよォ、こんなコトをイチから作るのってムズカシくねえか?
たしかに、頭で考えてココまで作るのはタイヘンそうだよね。
うん、サスガになにもかも2進数で考えてプログラムに組むのはムズカシいだろうね。だけどビット演算にはいくつか必勝法になるパターンがあるんだ。BUTTON()命令で使ってる数の組み合わせもそのひとつだよ。
つまり……その必勝パターンと使い方をオボエれば、ウマくプログラムに使えるってのか?
そういうコトなんだけど……
?
その話をするともっと長くなっちゃうから、また今度にしよう!
ウォオー!! 今回の話がオレのプラスになったのかどうか、サッパリわからねー!!
なかなかタイヘンじゃったようじゃのう。しかしワンパク君、ここでオボエたコトはけっしてムダにはならんぞい。ツギのサンプルプログラムでもビット演算がさっそく出てくるくらいじゃ。
- BIN$(数値)
- &B1011
0111 | |
AND | 1011 |
= | 0011 |
0101 | |
OR | 0011 |
= | 0111 |
0101 | |
XOR | 0011 |
= | 0110 |
NOT | 1101 |
= | 0010 |
表示モード : [ スマホ・3DS対応表示 | クラシック表示 ]
PukiWiki 1.4.7 Copyright © 2001-2006 PukiWiki Developers Team. License is GPL. Based on "PukiWiki" 1.3 by yu-ji
ページの処理時間 : 0.544 秒 | このページの最終更新 : 2022/09/20 (火) 12:49:33 (565d) | ログイン
Copyright(C) 2011-2014 プチコンまとめWiki ◆1sxkymI8ji30