後編
(分岐と反復、関数と関数呼び出し、ラベルとキー入力、その他)
特別編
anonymous>よう俺。コンフィグのところでよく使われてる&が一つしかない文ってどういう意味なんだ? &&の間違い?
anonymous>ああ、それはビット演算ってやつだな。
ここにちゃんと載ってる
anonymous>一番下のやつな
---------------------------------------
anonymous>……よし、さっぱりだ
anonymous>だろうと思った。二進数なんて普段使わないだろうしな
anonymous>そもそも二進数?それおいしいの?な俺に隙は
anonymous>仕方ないな、まずはそこから説明してやろう
EX1)二進数
○二進数とは
その方面について勉強している人でもなければ馴染みは薄いと思われる
二進数ですが、ビット演算を利用するなら是非覚えておきましょう。
日頃よく使われる数字、0,1,2,...,9,10,11,...99,100,101,...
これらは十進数と言われます。そーなのかー
他にも○進数と呼ばれる数値の表現はありますが、その見分け方として
桁上がりするタイミングで見るのを覚えましょう。
十進数なら0,1,2,3,4,5,6,7,8,9,10,11,...というように
9の次で二桁になります。10から二桁→十進数ということですね。
つまり二進数なら2で二桁となります。
0 - 0
1 - 1
10 - 2
11 - 3
100 - 4
101 - 5
110 - 6
111 - 7
1000 - 8
上に並べた9つの数字は同じ数値を二進数と十進数で表したものです。
右の列が馴染み深い十進数ですね。
一方の左、二進数の列を見てみると2,4,8と2のX乗の数になるごとに
桁が増えているのがわかると思います。
これが二進数の表し方の基本となります。
二進数については
・全ての桁は常に0か1である
・2のX乗ごとに桁が増える
この二点を覚えておきましょう。
○よくわかる二進数→十進数の直し方
桁が2のX乗に云々というのでは難しいので、二進数を十進数に直す時は
こう見るといいでしょう。
例)
1011011→(64*1+32*0+16*1+8*1+4*0+2*1+1*1)
→(64+16+8+2+1)→91
anonymous>こんなものか
anonymous>んー……まあ何となくわかった……かな
anonymous>しかし、これがコンフィグなんかとどう関係するんだ?
anonymous>うむ。eraのコンフィグってのはこの機能を使う・使わないで設定するよな?
anonymous>ああ、そうだな。各項目にONとかOFFとか出てるしな
anonymous>二進数は1か0しか使わない、これはさっき理解したよな?
anonymous>ああ、そうだったな
anonymous>ということは?
入室 anonymous anonymous!anonymous@anonymous.
anonymous>にんっ
anonymous>しんっ
anonymous>すうっ
anonymous>なるほど。各機能のONに1を、OFFに0を対応させて見るわけか
anonymous>そういうことだ
anonymous>次はそれを実際にどう書くかだな
EX2)ビット演算
○ビット演算とは
前項で二進数が各桁1か0で表される数値であることを勉強しました。
ビット演算ではこの各桁が1であるか0であるかを判定することによって
条件分岐に使用したりします。
例)
FLAG:1 = 0
FLAG:2 = 1
IF FLAG:1 & 1
PRINTFORML FLAG:1はONです。
ELSE
PRINTFORML FLAG:1はOFFです。
ENDIF
IF FLAG:2 & 1
PRINTFORML FLAG:2はONです。
ELSE
PRINTFORML FLAG:2はOFFです。
ENDIF
&はその前後の値を二進数に直し、同じ桁が1であるものを1、それ以外の
桁を0として計算し、それを並べた結果を十進数で表します。
FLAG:1 & 1を見る時、まずFLAG:1の値は0、二進数でも0です。
それと比較する1は二進数でも1ですから、0と1で一致しません。
つまり、FLAG:1 & 1は0となります。
一方FLAG:2 & 1の方では、FLAG:2も1も二進数で1となります。
どちらも一桁目が1なのでFLAG:2 & 1は1となります。
これを上のIF文に当てはめると
IF 0
PRINTFORML FLAG:1はONです。
ELSE
PRINTFORML FLAG:1はOFFです。
ENDIF
IF 1
PRINTFORML FLAG:2はONです。
ELSE
PRINTFORML FLAG:2はOFFです。
ENDIF
となり、表示される結果はこのようになります。
FLAG:1はOFFです。
FLAG:2はONです。
○複数の条件を判定する
上の例ではFLAG:1,FLAG:2それぞれに1つずつの条件を判定する
処理を説明しましたが、ビット演算を利用すると一つのフラグで複数の
条件を判定させることができます。
例)
IF FLAG:1 & 1
PRINTFORML 条件1はONです。
ELSE
PRINTFORML 条件1はOFFです。
ENDIF
IF FLAG:1 & 2
PRINTFORML 条件2はONです。
ELSE
PRINTFORML 条件2はOFFです。
ENDIF
IF FLAG:1 & 4
PRINTFORML 条件3がONです。
ELSE
PRINTFORML 条件3がOFFです。
ENDIF
このようなIF文がある時、FLAG:1の値によって結果はどうなるでしょうか。
まずFLAG:1が0の時、先の例でもあったようにFLAG:1 & 1は0です。
FLAG:1 & 2を見ると、0(00)と2(10)でどちらも1になる桁はなく
やはり0になります。FLAG:1 & 4も0(000)と4(100)で0ですね。
次にFLAG:1が1の時、これも先の例の通りFLAG:1 & 1は1です。
FLAG:1 & 2は1(01)と2(10)なので0、
FLAG:1 & 4も1(001)と4(100)で0になります。
FLAG:1が2の時、FLAG:1 & 1は2(10)と1(01)で0です。
FLAG:1 & 2は2(10)と2(10)で二桁目がどちらも1になりました。
このため、FLAG:1 & 2は二進数で10、つまり2になります。
FLAG:1 & 4は2(010)と4(100)で0になります。
FLAG:1が3の時、FLAG:1 & 1は3(11)と1(01)で一桁目が一致し
1になります。FLAG:1 & 2では3(11)と2(10)で二桁目が一致し
2になります。FLAG:1 & 4は3(011)と4(100)で0です。
FLAG:1が3の時の結果表示はこのようになります。
条件1はONです。
条件2はONです。
条件3はOFFです。
このようにビット演算を利用することで複数の条件の組み合わせを
一つのフラグで表現することができます。
ただし、判断できる条件はON/OFFやあり/なしなど二択のものに
限られることに注意しましょう。
また、条件一つ一つの判断を行う式で&の後に使う数値は2のX乗の値を
使います。理由は後の項で説明します。
○ビット演算で使う値を設定するには
ここまではビット演算での判定を行う部分について説明してきました。
しかし、実際に処理中でビット演算を利用するには判定に使われる
値を動かす方法も必要となってきます。
他の処理のようにFLAG:1 += 1やFLAG:1 -= 2と計算を行っても
いいのですが、この方法だと問題が発生する場合があります。
例)
FLAG:1 = 0
@CONFIG_1
PRINTFORML [0]機能1をONにする
PRINTFORML [1]機能1をOFFにする
INPUT
IF RESULT == 0
PRINTFORML 機能1をONにします。
FLAG:1 += 1
ELSEIF RESULT == 1
PRINTFORML 機能1をOFFにします。
FLAG:1 -= 1
ENDIF
@PRINT_CONFIG
SIF FLAG:1 & 1
PRINTFORML 機能1がONです。
SIF FLAG:1 & 2
PRINTFORML 機能2がONです。
SIF FLAG:1 & 4
PRINTFORML 機能3がONです。
・・・(以下略)
このような処理があった場合、「機能1をONにする」というコマンドを
2回以上実行してしまうとFLAG:1の値が2,3,4,...と増え続けるため
正しく動作しない可能性があります。
そこで、ビット演算の判断用変数の計算に使われるのが | です。
| は前後の値を二進数に直した時、同じ桁同士でどちらか片方でも
1となる桁を1にする計算を行います。
例えば、5(101) | 3(011)なら三桁とも1となるので
結果は二進数で111、つまり十進数だと7になります。
A = 5
B = 3
C = A | B
PRINTFORML 変数Cは{C}です。
↓
変数Cは7です。
また、A = A | B は A |= B と書くこともできます。
ビット演算に使用する変数は元のものに上書きすることが多いため
ぜひ覚えておきましょう。
では逆に、機能をOFFにしたりする時にはどうすればいいでしょうか。
上の例で、今度は機能1・2・3全てONの状態とし、そこから機能2を
OFFにする方法を考えてみましょう。
まず、機能1~3がONということはFLAG:1 & 1もFLAG:1 & 2も
FLAG:1 & 4も0でない、つまりFLAG:1を二進数で表した時の下三桁は
111となっています。
ここから機能2をOFFにするには、他の桁はそのままでFLAG:1 & 2が0、
つまり下から二桁目のみを0にすればいいということになります。
二桁目を0にするなら二進数の10、つまり十進数の2を引けばいいと
考えることもできますが、それでは先の例のように2回以上行われた時に
数値がおかしくなってしまいます。
そこで再び使うのが&です。
7(111) & 5(101)の結果は二進数で101となり、他の桁を変えずに
二桁目だけ0にすることができました。
機能1・2がONの状態から機能2をOFFにするには、011を001にする
必要がありますが、これも3(011) & 5(101)で実現できます。
それでは、ここで&の後に持ってきた5(101)はどういう値なのでしょうか。
二進数で見ると、0にするべき二桁目以外が1の数値、と言えますね。
これは切り替える機能の総数が増えても同じことで、5個の機能の中で
4つ目をOFFにするなら10111、10個の機能の中で3つ目をOFFにするなら
1111111011を&の後に持ってくればいいことになります。
これらを踏まえて先の例のON/OFF部分だけを書き換えてみると
@CONFIG_1
PRINTFORML [0]機能1をONにする
PRINTFORML [1]機能1をOFFにする
INPUT
IF RESULT == 0
PRINTFORML 機能1をONにします。
FLAG:1 |= 1
ELSEIF RESULT == 1
PRINTFORML 機能1をOFFにします。
FLAG:1 &= 6(→110→2+4)
ENDIF
となります。
(FLAG:1 &= 6 は FLAG:1 = FLAG:1 & 6 と同じ処理になります)
anonymous>ということだ。わかったか?
anonymous>………………
anonymous>……まあ、実際わかるように説明できた自信もないからな
anonymous>あとは自力でやってもらうしかないな
anonymous>説明を見ながら自分で組んでみたり、使われてるバリアントやパッチの構文を追ってみたり、方法はあるんだ
anonymous>うーむ……
退出 anonymous 霊夢様は俺のy……主 anony!anony@anony.
anonymous>橙曰く、分からなかったら人肉、じゃない人に聞くだな
anonymous>IRCでもスレでも、奇特な職人様がいれば答えてくれるだろう
anonymous>そうだな……まあ何とか頑張ってみるよ
anonymous>おう。何かは知らんが完成待ってるよ
最終更新:2008年12月08日 18:31