Part 3.変数の定義域(3)

プログラのたみ!


for文にせよ、while構文にせよ、条件を満たすまでループを行なうためのものである。
たとえば以下のループ構文について考えてみよう。


while ( a<=p && p<= b)


変数pが区間[a,b]の範囲にある間、ループする。もう少し違う言い方をすれば、この区間[a,b]を集合Aとして、p∈A (pが集合Aに元として含まれる) とき、ループする。


つまり、このループから脱出するためには、pが集合Aの外に出なければならない。よって、変数pの定義域は、少なくとも集合Aより大きな集合でなければならない。プログラマ向けの説明をするならa=0,b=255(byteで表せる範囲)だとすれば、pの型は、少なくともbyteより大きな型、すなわち、shortとかintとかでなければならない。


この視点で見れば、


for(int i=0;i<256;++i)


というループ構造は、iが区間[0,255]にあるとき、ループして、この集合から外に出たときにループを脱出する。ループの脱出の仕方は、iをインクリメントしているので255を超えて抜けるだけであり、マイナスになって抜けることは考慮しなくて良い。


興味深いのは、この脱出判定は、インクリメントのあとに行なわれるということだ。インクリメントの「後判定」になっている。これを「前判定」に書き換えられるか考えてみよう。


int i=0;
while (true) {
// 処理

if (i==255) break;
++i;
}

こう書けば、ループを脱出するまでのインクリメントの回数は255回とforで回すより一回少なくて済むし、iは区間[0,255]さえ定義域として含んでいれば十分である。つまりbyte型で十分である。同様にある数から0になるまでダウンカウントするようなループの場合も、前判定にすれば(マイナスを取れる必要がないので)無符号型で十分である。


このようなメリットがありながら、実際に前判定でループを書くことは滅多に行なわれない。ここで、その理由について考えていこう。(つづく)