キャスト
切り捨てられた平均を直す
前回、合計 221 点の平均が 73 点になりました。本当は 73.666... です。今回はこれを正しく出します。
原因は割り算そのものにある
まず、次のコードでは直りません。
double average = total / 3;
printf("%.1f\n", average); /* 73.0 */受け取る側を double にしても、73.0 と出るだけです。total / 3 を計算する時点で、両方とも int なので結果は int になり、そこで 73 に切り捨てられています。あとから double の箱に移しても、消えた 0.666 は戻ってきません。
直すべきなのは、割り算をする前です。
キャストで型を一時的に変える
値の前に (型名) を書くと、その値をその型として扱えます。これをキャストと呼びます。
double average = (double)total / 3;
printf("%.1f\n", average); /* 73.7 */(double)total で、割られる数だけを double にしています。C では、割り算の左右で型が違うと、小さいほうが大きいほうに合わせられます。ここでは int の 3 が double の 3.0 として扱われ、割り算全体が小数の割り算になります。結果は 73.666... となり、切り捨ては起きません。
(double)(total / 3) と書くと丸かっこの中が先に計算されてしまい、73.0 に戻ります。キャストはかっこの位置で意味が変わります。
3つの書き方はどれも通る
次の3つはどれも小数の平均になります。片方が double なら十分だからです。
(double)total / 3
total / (double)3
total / 3.0いちばん短いのは total / 3.0 です。ただ、割る数が変数のときは 3.0 と書けないので、(double) を付ける形を覚えておくと応用が利きます。
表示の桁を決める
%f のままだと 73.666667 と6桁出ます。前回の書式指定を使って %.1f と桁を決めてください。この講座の採点は出力を1文字ずつ比べるので、桁を指定しないと不合格になります。
キャストは切り捨てにも使える
逆向きのキャストもできます。(int)73.9 は 73 です。四捨五入ではなく小数を捨てるだけ、という点は int の代入と同じです。四捨五入したいときは 0.5 を足してから int にする、という手が使えます。
printf("%d\n", (int)73.9); /* 73 */
printf("%d\n", (int)(73.4 + 0.5)); /* 73 */
printf("%d\n", (int)(73.6 + 0.5)); /* 74 */事故に気づくための目印
平均を小数で出したはずなのに、.0 ばかりが並ぶときは、ほぼ確実にどこかで int どうしの割り算をしています。逆に、小数で出したいのに %d で出そうとすると、値がまったく別の数になります。
この2つは C の初学者がいちばん長く悩む場所です。「割る前にキャストできているか」「出す印は値の型と合っているか」の2点を、その場で確かめる癖を付けてください。次回の比較演算子と合わせて、この章の残りはあと2回です。
要件
- 3つの点数を scanf で読む
- 合計は int で出す
- 平均はキャストを使って小数のまま計算する
- 平均は小数点以下1桁で出す
- 「合計は221点です」「平均は73.7点です」の形で2行出す
入出力例
main("80 75 66") → "合計は221点です
平均は73.7点です"
main("90", "85", "70") → "合計は245点です
平均は81.7点です"