見出し画像

高等学校「情報Ⅰ」文科省研修用教材を検証する(3):誤差の問題

高等学校情報科「情報I」 教員研修用教材をあらためて読む。いよいよ第3章のプログラミングである。
ここでは単なる批判ではなく,できるだけ「補充」ということにしたい。

今回は「誤差」

コンピュータで計算誤差が生じる理由について,このような解説と図がある。

コンピュータで変数は指定され たビット数の箱に入っていると考える。この箱 ( 定められたビット 数 ) に収まるものであれば誤差は 生じないが,収まらないものは誤差が生じる。例えば,15 ビットの箱を準備したとき,13 ビットの魚 A は箱に収まるが,20 ビットの魚 B は 箱に入らない。このとき失われた 5 ビットが計算誤差の原因となる。

画像1

わかりやすい。
ただし,本当に理解するためには,コンピュータで扱う数のデータ型についての知識が必要だ。
その説明は次のようになされている。

コンピュータでは,数値は小数点を含まない「整数」,または小数点を含む「浮動小数点数」のどちらかで扱われる。これらの数値は,コンピュータの内部では固定の桁数で扱われることが多い。

「固定小数点数」については言及されていないが,まあ,整数型と浮動小数点数型でよいだろう。ただし,それが実際にはどんなものなのかの説明はない。整数が8ビットから64ビットまでいろいろあるとか,浮動小数点数にも32ビットと64ビットがあることは書かれていない。もっとも,C言語でプログラムを書くのでなければ必要ないかもしれないが。

次に,こう書かれている。

float 型で指定した変数に桁数の多い数字や,その変数型で扱うことのできる最大値より大きい数字を代入して 表示するプログラムと実行例を示す。

float は浮動小数点数のことだが,いきなり float型 でわかるだろうか。
また,そのあとに,float 型で表される最大値を調べて,その数の仮数部に値を追加したり,それより大きな値を変数に代入するとオーバーフローする,という Pythonのプログラムが載っている。
それはそれでいいのだが,次に,

また,整数同士の減算と小数同士の減算のプログラムを実行してみると以下のようになる。

として,次のプログラムと実行結果が載っている。

画像2

これには

小数の 0.28 から小数 0.27 を引くと,本来であれば計算結果は 0.01 になるはずだが,プログラムを実行した 結果を見ると 0.01 にはならず,コンピュータの計算誤差が発生していることが分かる。

という説明がついているが,なぜそうなるかは書かれていない。浮動小数点数の説明がきちんとなされていないからだ。

コンピュータの計算誤差については,現行の教科書では取り上げていない。1冊だけ,「誤差が出る」と書いたものがあったが,その仕組みの解説はなかった。浮動小数点数の説明もほとんどない。

プログラミングをしなくても,表計算ソフトのExcelでも生じることがある。筆者は,実際に経験している。あるコンクールの集計をしていたとき,同じ点であるにもかかわらず同順位にならないという現象があった。幸い途中経過での集計だったので修正は間に合ったが,最終段階で起きていたら慌てただろう。もし「コンピュータでは計算誤差が起こる」ことを知っていなかったら手も出せないかもしれない。筆者は知っていたので,集計の方法から考えて,「適当な桁数で四捨五入する」という方法で切り抜けた。
Excelでは,他にもいろいろ計算誤差が起こる場面があるが,バージョンアップするたびに改善されてきている。すなわち,処理系で誤差の問題を吸収しているのである。
 よく使われる表計算ソフトでも起こることなので,筆者の授業では,早い時期(情報のディジタル化)に誤差を扱っている。そのために,教科書には載っていない,十進小数から二進数への変換もやっている。0.1が2進数では無限小数になることを確かめさせ,それを途中で打ち切るために誤差が起こることを説明。
参考書は,古い本だが「数値計算の常識」(伊理正夫・藤野和建 共立出版)である。
 そのあと,実際にExcelやプログラミング言語で実験をする。
(1) A1セルに 8.7 ,B1セルに 5.4 を入れる。
(2) C1セルに =IF(A1-B1>=3.3,1,0) を入れる。
(3) A2セルに 18.7 ,B2セルに 15.4 を入れ,C2 , D2 セルはC1, D1 セルをコピー
A3セルに 108.7 ,B3セルに 105.4 を入れ,C3 , D3 セルはC2, D2 セルをコピー
 A4セルに 208.7 ,B4セルに 205.4 を入れ,C4 , D4 セルはC3, D3 セルをコピー
 結果はどうなるか。

としたあと,セルの表示桁を16桁まで増やすと誤差が出ていることがわかる。
その他,R,Python(Ver2)を使って簡単な小数の引き算をやってみせた(やらせた)こともある。勤務校のパソコン室のパソコンには,R,Pythonが入っている。

 ところで,研修用教材であるが,この例は,コンピュータの内部処理の問題であって,変数に代入しなくても誤差は確かめられる。単に 0.28 - 0.27 でよい。他の数でもよい。これだけの計算ならば,Jupyter notebook など立ち上げなくても,コマンドラインでいける。

画像3


0.25-0.125 がちゃんと 0.125 になっているのは,2進数にしたとき有限桁だからだ。このような例もやっておかないと,小数の計算はいつも誤差が出るという誤解を与えかねない。誤差が出る原理を確認するために必要だろう。

 処理系(プログラミング言語)によっては,このような誤差に対する何らかの処理はしてあるものもある。たとえば,Rでは,ちゃんと 0.01 になる。ただし,表示上のことであり,内部では 0.01 にはなっていない。

画像4


Mathematica も同様。もちろん無料の Wolfram Engine でも同じだ。

画像5

研修用教材のJavaScript版には,次のコードが示されている。

<script>
x = 28-27;
document.write(x+"<br>");
y = 0.28-0.27;
document.write(y+"<br>")
</script>

これも,

document.write(0.28-0.27)

だけでよい。

画像6


ただし,JavaScriptでは,たったこれだけのことでも,テキストファイルに書いてブラウザで実行しなければならない。
研修用教材のドリトル版にはこの例は載っていない。
VBA版にはあるが,変数に代入すると,変数の使用宣言も必要で,ほかにも書くことがあって面倒だ。

 以上,研修用教材で体験はできるが,やはり浮動小数点数についてはその原理だけでもきちんと学んでおくべきだろう。