見出し画像

高校数学をプログラミングで解く(数学A編)「3-9 分数と小数」

マガジンリスト > 数学A編 3.整数の性質 > 3-9 分数と小数


はじめに

今回は、数学Aで学ぶ「分数と小数」について、分数を小数で表すためのプログラムを作成します。

分数を小数で表す問題

分数を小数で表すためのプログラムを作成するにあたり、次の問題を考えます。

問題
次の分数を小数で表したとき、[]内の数字を求めよ。

$$
\frac{4}{11}  [\mathrm{小数第} 20 \mathrm{位}]
$$

この問題は、分数を小数で表したとき循環小数になることを考慮すると、比較的簡単に小数第20位の数字を求めることができます。実際、

$$
\frac{4}{11} = 0.\.{3}\.{6}
$$

と表せますので、小数第20位の数字は「6」になることがわかります。
ただ、今回は、循環小数であることを利用せずに、単純に分数を小数第20位まで求めることにより小数第20位の数字を求めるプログラムを作成します。

アルゴリズム設計「小数を求める手順」

素朴に考えると、小数を求めますので、浮動小数点数を扱うfloat型の値を扱えばよさそうです。しかし、そう単純にはいきません。実際、次のようなプログラムを作成します。

void setup(){
  println(4.0/11.0);
}

ソースコード1 分数を浮動小数点数で表すプログラム

ソースコード1を、Processingの開発環境ウィンドウを開いて(スケッチ名を「fraction_decimal_test」としています)、テキストエディタ部分に書いて実行すると、図1のように、コンソールに

$$
0.36363637
$$

と表示されます。つまり、浮動小数点数では有効桁数や丸め誤差などの影響で今回求めたい小数第20位までの値を求めることができません。

図1 スケッチ「fraction_decimal_test」の実行結果

そこで、この問題では、浮動小数点数を用いるのではなく、整数の配列を用いて小数を表すようにします。つまり、この整数の配列を$${D}$$で表すと、小数の整数部を$${D[0]}$$に代入し、小数の第 $${i}$$位の値を$${D[i]}$$に代入するようにします(図2参照)。

図2 小数を整数の配列に代入するイメージ

このようにすることで、小数は最初に設定する配列数の桁まで計算することができます。以下に整数の配列を利用した小数の計算方法についてまとめます。割り算の筆算をアルゴリズム化することを考えるとわかりやすいです。

図3 筆算の例

図3の筆算の例を見ながら、アルゴリズム化してみます。
① 割られる数を$${m}$$とし、割る数を$${n}$$とします。最初の段階では、問題となっている分数の分子を$${m}$$に、分母を$${n}$$に代入します。今回の場合、$${m=4}$$、$${n=11}$$となり、図4の筆算のステップに対応します。

図4 筆算①

② $${m}$$を$${n}$$で割ったときの商$${q}$$と余り$${r}$$を計算し、商$${q}$$を$${D[0]}$$に代入します。これは図5の筆算のステップに対応します。

図5 筆算②

③ $${m}$$に余り$${r}$$を10倍したものを代入して、更新します。これは図6の筆算のステップに対応します。

図6 筆算③

④ $${m}$$を$${n}$$で割ったときの商$${q}$$と余り$${r}$$を計算し、商$${q}$$を$${D[1]}$$に代入します。これは図7の筆算のステップに対応します。

図7 筆算④

⑤ あとは、③と④のステップを求めたい小数の桁数まで繰り返します。図3は、小数第4位まで繰り返したときの筆算となります。

プログラム

上記で解説した手順(アルゴリズム)を利用して、問題の小数第20位の数を求めるプログラムを作成します。

// 分数の小数第a位の数を求める
void setup(){
  
  int numerator = 4; // 分子
  int denominator = 11; // 分母
  int a = 20;  // 小数の第何位の値をもとめるか
 
  // 分数を小数第a位までの値を格納する配列
  // 0番目に整数部、i番目に小数第i位の値が入る
  int[] decimal = new int[a+1];
  int m = numerator; // ①割られる数を準備
  int n = denominator; // ①割る数を準備
  int q, r; // 商と余り
  for(int i=0; i<=a; i++){
    q = m/n; // ②④商を計算
    r = m%n; // ②④余りを計算
    decimal[i] = q; // ②④商を代入
    m = r * 10; // ③余りを10倍して割られる数を更新
  }
  println(decimal[a]);
}

ソースコード2 分数の小数第20位の数を求めるプログラム

ソースコード2を、Processingの開発環境ウィンドウを開いて(スケッチ名を「fraction_decimal」としています)、テキストエディタ部分に書いて実行すると、図8のように、コンソールに分数を小数で表したときの小数第20位の値「6」を出力します。

図8 スケッチ「fraction_decimal」の実行結果

おまけ「小数を出力」

今回は小数第20位の値を求めました。おまけとして、ソースコード2にコードを追記して、分数を小数第20位まで表すプログラムにしてみます。これは簡単で、ソースコード3に示すように、ソースコード 2に各小数の桁をコンソールに出力するコードを追加すると実現できます。つまり、最初の整数部分を出力した後、小数点を出力し、あとは小数の値を順番に出力していけばいいだけです。

// 分数を小数第a位まで求める
void setup(){
  
  int numerator = 4; // 分子
  int denominator = 11; // 分母
  int a = 20;  // 小数の第何位までもとめるか
 
  // 分数を小数第a位までの値を格納する配列
  // 0番目に整数部、i番目に小数第i位の値が入る
  int[] decimal = new int[a+1];
  int m = numerator; // ①割られる数を準備
  int n = denominator; // ①割る数を準備
  int q, r; // 商と余り
  for(int i=0; i<=a; i++){
    q = m/n; // ②④商を計算
    r = m%n; // ②④余りを計算
    decimal[i] = q; // ②④商を代入
    m = r * 10; // ③余りを10倍して割られる数を更新
    print(decimal[i]);
    if(i==0){
      print(".");
    }
  }
//  println(decimal[a]);
}

ソースコード3 分数を小数第20位まで求めるプログラム

ソースコード3を、スケッチ「fraction_decimal」のテキストエディタ部分に追記して実行すると、図9のように、コンソールに分数を小数第20位まで出力します。

図9 ソースコード3の実行結果

練習問題

次の分数を小数で表したとき、[]内の数字を求めよ。

$$
\mathrm{(1)}  \frac{24}{37}  [\mathrm{小数第}50\mathrm{位}],  
\mathrm{(2)}  \frac{11}{101}  [\mathrm{小数第}75\mathrm{位}],  
\mathrm{(3)}  \frac{66}{205}  [\mathrm{小数第}100\mathrm{位}] 
$$

まとめ

今回は、数学Aで学ぶ「分数と小数」について、分数を小数で表すためのプログラムを作成してみました。
小数を扱う場合、単純に考えると浮動小数点数を利用すればよさそうですが、小数第20位のように大きな桁まで小数を求めたい場合、浮動小数点数では有効桁数や丸め誤差などの影響で正確には求めることができません。
そこで、今回は浮動小数点数を利用する代わりに、整数の配列を利用しました。つまり、小数の各桁の数を整数の配列に格納していくわけです。これを行うことで、大きな桁数の小数でも表すことができます。この場合の演算には少し工夫が必要ですが、計算の仕方を順番に追っていけばそんなに難しいことはないです。
整数でも、小数でも大きな桁数を正確に表したい場合は、この整数の配列を利用すれば表すことができます。ぜひこのような考え方に慣れていってください。

参考文献

改訂版 教科書傍用 スタンダード 数学A(数研出版、ISBN9784410209277)

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