C プログラミング (C Programming)

[2017/09/25, H.Aman]
[← 演習のページへ戻る]

サンプルプログラム 3 の内容

二つの整数を読み込み,それらの平均値を出力しています.
ただし,キャストを行わなかった場合に正しく動作しない例も含めています.
 1:   #include <stdio.h>
 2:  	
 3:   int main(void){
 4: 	 int x, y;
 5:      double avg;
 6:
 7:      printf("二つの整数を入力してください:");
 8:      scanf("%d %d", &x, &y);
 9:
10:      avg = (x + y)/2;
11:      printf("平均値(誤)= %f\n", avg);
12:      
13:      avg = (double)(x + y)/2;
14:      printf("平均値(正)= %f\n", z);
15:
16:      return 0;
17:   }

10 行目:avg = (x + y)/2;

 7:      printf("二つの整数を入力してください:");
 8:      scanf("%d %d", &x, &y);
 9:
10:      avg = (x + y)/2;
11:      printf("平均値(誤)= %f\n", avg);
12:

平均値を求めるのが目的ですので, x と y を足して,その答えを 2 で割るという計算式は合っているように見えます.

しかし,残念ながら実際に動かしてみると,小数点以下が全部 0 になっていて, (例えば,3 と 8 の場合,平均値は 5.5 ですが)平均値として 5 が出力されます.
実のところ,計算の過程で小数点以下が切り捨てられてしまっています.

その理由は,(x + y)/2 という計算式で登場する変数と定数にあります. ここでは x, y, 2 という三つが登場しますが,いずれも int 型(整数)です.
x = 3, y = 8 の場合を例に順を追ってみていきましょう:
  1. まずは (x+y) が計算されます.
    つまり,(3+8) が計算され,これが 11 という整数(int 型)になります.
  2. 次に (x+y)/2 ですが,(x+y) は 11 であることが分かっていますので,
    11/2 と解釈されます.
    ここでポイントになるのが,11 と 2 は両方とも int 型(整数)であるということです.
    それゆえ,計算結果は 5.5 ではなく, 11 を 2 で割った商である 5 になります
    小数点以下が切り捨てられると考えても構いません.
  3. 結果,せっかく受け皿として double 型の avg を用意していたのですが, そこには小数点以下が切り捨てられた 5 が代入されます.

13 行目:avg = (double)(x + y)/2;

10:      avg = (x + y)/2;
11:      printf("平均値(誤)= %f\n", avg);
12:      
13:      avg = (double)(x + y)/2;
14:      printf("平均値(正)= %f\n", z);

上の問題を解決するため, double 型への型変換(キャスト)を行います.

ここでも x = 3, y = 8 の場合を例に順を追ってみていきましょう:
  1. (double)(x + y)/2 という式は次のように解釈されます.
    (double) と書いてあるので,そのすぐ後ろにくる値を double 型に変換します.
    そうして得られた値を 2 で割ります.
  2. (double) のすぐ後ろの値というのは,(x+y) の計算結果になります.
    つまり,(3+8) が計算され,11 という整数(int 型)になります.
    するとこの部分では,11 という整数を double 型(実数)に変換します.
    よってこの値は 11.000000 という扱いに変わります.
  3. (double)(x+y)/2 ですが,(double)(x+y) は 11.000000 であることが分かっていますので,
    11.000000/2 と解釈されます.
    今度は double 型と int 型が混在した計算式になりますが, これはサンプルプログラム 2 で見たように,自動的にすべて double 型として扱われます. それゆえ,計算結果は 5.500000になります.