余りの計算

底辺b,高さhの三角形の面積Sを計算するCプログラムを書きなさいという問題があって
S=1/2*(b*h);
と書いて,どんなに大きなb,hでも0になってしまうのはなぜだろうと悩んだことはありますか?私はあります。もちろんこれは整数割り算だからです。
「1÷2はいくつ?」と聞かれたときに,初めは「0あまり1」だったのに「0.5」とか「1/2」になったのはいつからだったのでしょうか?私はあまりに昔過ぎて忘れました。今回はしばらく使うのを忘れていた(であろう)この「余り」が意外と便利かもという話を書きます。

※C言語では%で剰余算を表します。例えば,10%3は1です。
負の数に対する剰余算はややこしいのでここでは%の前も後ろも正の数のみの話にしておきます。

さて,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
という数について3で割った余りは
0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0
です。0,1,2のパターンを繰り返します。
このことを一般化すれば,
0,1,2,3,4,5,6,7,8,9,10,...
に対してnで割った余りは
0,1,2,...,n-1
の繰り返しです。
これは馴染みのないことでもありません。時計の時は
1,2,3,4,5,6,7,8,9,10,11,12
と繰り返すことは馴染みがあるでしょう,時計は何百,何千時間と時を刻みますが,1時,2時と続き,12のあとは13でなく1,続いて2と繰り返していきます。針式の時計のてっぺんに12(またはローマ数字のXII)が書かれてますが,デジタル表示なら0時です。ですから,
0,1,2,3,4,5,6,7,8,9,10,11
あるいは0から23を繰り返す数は馴染みがあるはずです。
これは図的には無限に続く線のように思える時の流れを12時間あるいは24時間ごとにくるくる回る曲線のように描くとイメージがつかみやすいです。
そしてこの周期が12とか24でなく一般の数字であったらと考えると剰余のイメージがしやすいです。(昔学習百科事典の数学の本でこの説明を読みとてもわかりやすかったことを思い出しながら書いてますが文字だけだと余り伝っていないかも…)

1,2,3,4,...というカウントをnで割った余りにすると0からn-1の繰り返しになります。

このことの応用として,例えば4枚の絵があり,1フレームごとに表示する絵を変えてアニメーションとして見せたいとします。例えば,4枚の絵がa.jpg, b.jpg, c.jpg,d.jpgだとして疑似的にコードを書くと

初期化{
 a.jpgを表示する。
}
フレームごと繰り返し{
 1フレーム前に表示したのがa.jpgだったらb.jpgを表示する。
 1フレーム前に表示したのがb.jpgだったらc.jpgを表示する。
 1フレーム前に表示したのがc.jpgだったらd.jpgを表示する。
 1フレーム前に表示したのがd.jpgだったらa.jpgを表示する。
}

というような感じでもよいのですが,ちょっと細工して剰余で書けます。3枚の絵がpic[0].jpg, pic[1].jpg, pic[2].jpg, pic[3].jpgだとして,

初期化{
 count←0
}
フレームごと繰り返し{
 pic[count%4]を表示
 count←count+1
}

とした方がすっきりするし枚数が増えても%の後の数字を変えればよいです。ここで問題はcountがオーバーフローすることですが,まあ,countが32ビットなら,まあ大丈夫でしょう(気になる人は1秒30フレームとしてオーバーフローするまで何日かかるか計算してみてください)。
さらに,FPSが大きく絵の切り替えが早すぎるので3フレーム同じ絵を表示したいというならどうればよいのでしょうか?これは整数割り算を使います。

フレームごと繰り返し{
 pic[(count/3)%4]を表示
 count←count+1
}

わかるでしょうか?これは数の列を書き下してみると納得してもらえると思います。
count
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23
に対して
count/3は
0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7
となり,((count/3)%4)は
0,0,0,1,1,1,2,2,2,3,3,3,0,0,0,1,1,1,2,2,2,3,3,3
となります。
一般にn枚の絵をmフレーム表示することを繰り返すのは

フレームごと繰り返し{
 pic[(count/m)%n]を表示
 count←count+1
}

となります。繰り返しますがカウンター変数のオーバーフローは無視できるとしています。


この記事が気に入ったらサポートをしてみませんか?