りょうのゲーム塾 -117ページ目

りょうのゲーム塾

再開、準備中。

チェックポイント
前回はコンピュータの扱う2進数を我々の扱う10進数へ変換してみました。
今回は逆に10進数を2進数に変換してみます。
ここでは変換を覚える必要はありませんが、なぜこの様な知識が必要なのかは覚えておいてください。
プログラミングする際に必要な知識とつながっています。


まず整数の10を2進数に変換してみます。
変換する場合は2で割っていきます。
このときの商と余りを記述します。

10 ÷ 2 = 5 … 0

商は5なのでまた割ります。

5 ÷ 2 = 2 … 1

商は2なのでまだ割ります。

2 ÷ 2 = 1 … 0

これで商がになりました。
ここまで計算します。

10 ÷ 2 = 5 … 0 ←④
5 ÷ 2 = 2 … 1 ←③
2 ÷ 2 = 1 … 0 ←②
        ↑
        ①

①から④へ順番に左から右へ書き直します。

  ①②③④
  ↓↓↓↓
&B1010

すると2進数に変換されています。

では実数の場合はというと、実数の整数部は整数なので上の方法で変換できます。
小数部も理論的には同じなのですが変換する方法を変えてみましょう。

たとえば少数0.75はどうなるでしょうか?
この場合1を2で割っていきます。
その商が変換する値から引けた場合には引いて1を横に記述します。
引けないときは0を記述していきます。
小数部の計算終了は2進数何桁目まで計算するかで決まります。
ここでは4桁まで計算してみましょう。

                   0.75
まず 1 ÷ 2 = 0.5   - 0.5
                 ────────
                   0.25    引けたので … 1 ←①
0.5 ÷ 2 = -0.25  - 0.25
                 ────────
                      0    引けたので … 1 ←②

今回は4桁計算する前に0になったので終わります。

これを①から②へ順番に左から右へ書き直します。

すると1100となります。

たとえば実数10.75の場合、整数部が2進4桁、小数部が2進4桁であらわされていたら、

&B1010▲1100  となります。(▲が小数点だとすると・・・)

プチコンの場合には小数部が12桁になります。

では本題の0.1はどうなるか…

  1                  0.1
÷ 2                - 0.5
──────────────────────────────
  0.5                0.1       引けなかった   0
÷ 2                - 0.25
──────────────────────────────
  0.25               0.1       引けなかった   0
÷ 2                - 0.125
──────────────────────────────
  0.125              0.1       引けなかった   0
÷ 2                - 0.0625
──────────────────────────────
  0.0625             0.0375    引けた      1
÷ 2                - 0.03125
──────────────────────────────
  0.03125            0.00625   引けた      1
÷ 2                - 0.015625
──────────────────────────────
  0.015625           0.00625   引けなかった   0
÷ 2                - 0.0078125
──────────────────────────────
  0.0078125          0.00625   引けなかった   0
÷ 2                - 0.00390625
──────────────────────────────
  0.00390625         0.00234375 引けた      1


え~・・・この時点で計算ミスしてるかもしれません^^;
計算はまだ続きます。

が・・・ここら辺で勘弁をm(__)m

ここまででわかってもらえますか?
このままだと12桁まで計算しても計算が終わりそうに無いことが・・・

そうです!
終わりません^^
その分は誤差として切り捨てられます。

ですから0.1を10回足して1にならないのはこの誤差のせいです。

少数つきで計算する場合このことを頭に入れておかないとループが終わらない無限ループというバグを生み出すことになります。


チェックポイント
我々が扱う数値は桁数が無限の数値を使います。
しかしコンピュータの使用する数値は扱う桁数が有限の数値を使います。
扱う桁数が有限であるのはコンピュータのメモリには限りがあるためです。
そのため扱える数値の範囲に限りがあるだけでなくある問題も生じます。


コンピュータは2進数を使っていますが、我々は10進数を使っています。
よって数値データの処理をする際に2進数と10進数の変換を行うことがあります。
ではここで2進数を10進数に変換する作業を実際にやってみましょう。

まず2進数を10進数に変換するには
2進数場合、n桁目の重み(値)は2の(n-1)乗となります。
要するに1桁目の重みは2の0乗となります。

普通この乗数を表すには基数の右上に上付き文字で数値を記述しますが、
ワープロでは問題ありませんが現状では表しにくいので下記のように記述します。

基数^乗数

たとえば2の0乗であれば

2^0

ということにしておきましょう。

たとえば下記の2進数を10進数に変換する場合にはn桁目の値と重みをかけてすべてを足せばいいわけです。

&B1011 の場合

1桁目の値は 1 です … 重みは 2^(1-1)=2^0=1 です。 掛けると 1×1 で 1 です。
2桁目の値は 1 です … 重みは 2^(2-1)=2^1=2 です。 掛けると 1×2 で 2 です。
3桁目の値は 0 です … 重みは 2^(3-1)=2^2=4 です。 掛けると 0×4 で 0 です。
4桁目の値は 1 です … 重みは 2^(4-1)=2^3=8 です。 掛けると 1×8 で 8 です。

これらをすべて足すと…  8+0+2+1=11 となります。


プチコンは32ビットで数値を表現しています。
ただし固定小数点方式ですが…

では普通に32ビットの場合はどうなるかを考えます。

1)コンピュータにおける32ビットの整数表現の場合

 3332 2222 2222 2111 1111 111
 2109 8765 4321 0987 6543 2109 8765 4321 桁目
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 1111 1111 1111 1111 1111 1111 1111 1111
                                        ▲少数点の位置

 0000 0000 0000 0000 0000 0000 1000 0000
 この場合8桁目が1なので→2^(8-1)=2^7=128です。

ちなみに2^nとは1に2をn回掛けるという意味です。(念のために)

2^7=(1×2)×2×2×2×2×2×2
   =(2×2)×2×2×2×2×2
   =(4×2)×2×2×2×2
   =(8×2)×2×2×2
   =(16×2)×2×2
   =(32×2)×2
   =64×2
   =128


2)プチコンにおけ32ビットの固定小数点方式の実数表現の場合

 2111 1111 111                       111
 0987 6543 2109 8765 4321 1234 5678 9012 桁目
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 1111 1111 1111 1111 1111 1111 1111 1111
                         ▲少数点の位置
           整数部                 小数部     

固定小数点は決められた位置に小数点があると想定して数値を表します。
整数部分は1の場合と同じです。
小数部分は桁数を下記の図のように表すと小数点すぐ右が小数部1桁目です。
このときのm桁目の重みは 2^(-m) です。

これは

  1
━━━
 2^m

です。


たとえば小数部1桁目の重みは

    1   
  ━━━
   2^1

    1
= ━━━
    2

= 0.5

あとは同じです。



今度は10進数を2進数に変換してみます。

つづく
チェックポイント
プチコンで扱う数値は固定小数点方式の実数です。
人が計算する場合その数値は固定小数点方式で表す方が一般的です。
ただし、同じ少数でも我々が計算する少数とコンピュータの少数は違うものなのです。
ここではそのことについて理解しておきましょう。


皆さん、次の計算を行った結果答えはいくつになりますか?

変数Xに0を入れておくき、変数Xに10回1を足します。
変数Xの内容はいくらでしょうか?

これをプログラムしてみます

■プログラム
0001 ' Sample program
0002 X = 0
0003 N = 10
0004 @LOOP
0005 X = X + 1
0006 N = N - 1
0007 IF N != 0 GOTO @LOOP
0008 PRINT X
0009 END


ここで変数Xに0を入れておきます。これが初期化です。
変数Nは足す回数を記憶しておきます。
10回足すので初期値として10を代入しておきます。
5行目で変数Xに1を足します。
6行目で加算回数を記憶している変数Nから1を引きます。
7行目で変数Nが0でないときはまだ10回加算していないのでラベル@LOOPへジャンプします。
変数Nが0のとき10回加算したので変数Xの内容を表示し終了します。

実際に実行してみると答えは・・・10ですよね。

では変数に0.1を10回足すとどうなるでしょうか?
サンプルプログラムを変更します。

■プログラム
0001 ' Sample program
0002 X = 0
0003 N = 10
0004 @LOOP
0005 X = X + 0.1
0006 N = N - 1
0007 IF N != 0 GOTO @LOOP
0008 PRINT X
0009 END


結果はどうでしょうか?
たぶん0.1を10回0にたしたのだから計算式は

0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1

ということで結果は1になるはずです。
実際にこのプログラムを実行したら結果はどうなるでしょうか?

つづく