C初級:実数の計算について

C言語初級カテゴリのロゴ画像C言語初級
スポンサーリンク

C言語で扱うことが出来る数値には大きく分けて整数と実数があります。
実数は小数点以下の数値を扱うことが出来る、という意味です。

整数を扱うことが出来る変数型は、char, short, int, long の4種類です。
実数を扱うことが出来る変数型は、float, double の2種類です。
最初に結論から言ってしまうと、

float型は使わずにdouble型を使って実数計算をしましょう。

理由はfloatよりdoubleの方が計算速度も速く誤差も少ないからです。
doubleの欠点はfloatよりメモリを倍消費することくらいでしょうか。(コンピュータのメモリが2GBとか8GBの時代です。欠点という程ではありません)

C言語:float型とdouble型の表現範囲

変数型バイト長保存できる数値の範囲
float41.17549e-38 〜 3.40282e+38
double82.22507e-308 〜 1.79769e+308

整数型には、unsigned int や unsigned long などの負数部分を省いた型が存在しますが、実数型のfloatとdoubleには存在しません。

ここから少し、算数が入るので嫌な方は読み飛ばしてください。(わたしなら読み飛ばします)

上記の表でe-38やe+38などとありますが、意味はそれぞれ10の-38乗10の38乗です。
そう考えるとfloatやdoubleは相当大きな数を扱える型であることが分かります。
double型は8バイトの範囲、float型は4バイトの範囲の数値が表せます。

doubleはfloatに比べてどれ位の差があるかと言うと

double型とfloat型の差は

8byte ー 4byte = 4byte

ビットに直すと

4byte = 32bit

2^32(2の32乗) = 4294967296

となり、実にdouble型はfloat型に比べて4294967296倍の数値を表現できることになります...と言いたいところですが、実数の表現方法は少し違っていてここでは説明は省きますがfloat型よりdouble型の方が精度も高く表現範囲も広いことは確かです。とは言え、無限に数値を表現できるわけではないと肝に命じておいてください。
詳しく知りたい方は、

浮動小数点数型と誤差 – 京都産業大学

にきちんと書かれています。

前置きが長くなりましたが、実数を扱うサンプルプログラムを示します。

サンプルプログラム 08double.c

/* 08double.c 実数の演算 */
#include <stdio.h>
int main(void)
{
    double x, y, answer;
     
    printf("2つの数の引き算をします\n\n");
 
    printf("数値1を入力してください: ");
    scanf("%lf", &x);
    printf("数値2を入力してください: ");
    scanf("%lf", &y);
 
    answer = x - y;     /* x-y の計算結果が変数answerに代入される */
    printf("\n%f - %f = %fです\n", x, y, answer);
     
    return 0;
}

実行結果

2つの数の引き算をします

数値1を入力してください: 10
数値2を入力してください: 5

10.000000 - 5.000000 = 5.000000です

解説
5行目でdouble型の変数x, y, answer を宣言しています。
xとyはキーボードから入力した数値をそれぞれ代入させます。
double型の実数として入力したい場合、scanf関数での入力書式は%lfとなります。
もし変数をfloat型で宣言していれば、入力書式は%fとなります。
ではなぜprintf関数では%fを使って表示しているのだ!と思った人は鋭いです。
これは仕様によるものです。でも間違えやすい部分だと思うのであえて書いておきます。

doubleの場合、printfは%f, scanfは%lfです。
floatの場合、printfもscanfも%fということです。

実行結果から分かるように小数点以下の表示は6桁です。
桁数の表示はprintf関数で設定できます。

例えばdouble型変数xの小数点以下3桁まで表示するなら

printf(“%.3f¥n”, x);

とします。ピリオドの次に桁数を表す数値を指定します。
小数点以下20桁まで(表示できるかどうかは別として)表示したいなら

printf(“%.20f¥n”, x);

といった感じです。

どこまで表現できるのか知りたいところですが、私の使っている環境では小数点以下17桁までが限度でした。

例えば次のプログラムで確認してみて下さい。

サンプルプログラム real.c

/* real.c */
#include <stdio.h>
int main(void){
    double x = 0.12345678901234567890123456789;
    printf("%.20f\n", x);
}

実行結果(わたしの環境の場合)

0.12345678901234567737

5行目で%.20fとして表示しています。小数点以下20桁まで表示という意味です。
しかし、上記の実行結果を見ると18桁目から数値があやしいです。
コンピュータって正確なイメージがありますけど、小学生でも簡単にできることが以外に出来なかったりします。
コンピュータも間違えるんだということです。

もう少し具体的な例で見ていきます。
消費税の計算です。

金額(税抜き価格)を入力すると税込価格を表示します。
2018年5月現在、日本の消費税は8%です。

よって計算式は、

金額 × 1.08 = 税込価格

となります。
サンプルを示します。

サンプルプログラム zeikomi.c

/* zeikomi.c */
#include <stdio.h>
 
int main(void)
{
    double kingaku, zeikomi;
    
    printf("税込価格を計算をします");
    printf("金額を入力して下さい : ");
    scanf("%lf", &kingaku);
    
    zeikomi = kingaku * 1.08;
    printf("税込価格は\\%.0f円です\n", zeikomi);
    printf("実際の計算結果:\\%f円\n", zeikomi);
    
    return 0;
}

実行結果

税込価格を計算をします
金額を入力して下さい : 980

税込価格は¥1058円です
実際の計算結果:¥1058.400000円

解説
12行目で税込価格を求めています。
13行目のprintf関数で書式指定に%.0fとしています。価格は基本的には小数点以下の数値が使われないため、小数点以下0桁という意味の%.0fを指定しています。
14行目は、実際の計算結果も参考に表示するための記述です。
上記実行結果では、小数点以下は4のため四捨五入して1058が表示されています。
切り上げを見たいのであれば、試しに入力を982円としてみてください。

ちなみに消費税の豆知知識として

消費税の端数(はすう)計算は、切り捨て、切り上げ、四捨五入いずれも可能

と消費税法に書かれています。

コメント