C言語の浮動小数点演算の注意点と精度問題をやさしく解説!初心者でも安心の入門ガイド
生徒
「C言語で小数を計算したいんですけど、ちゃんと正確になりますか?」
先生
「実は、C言語で扱う浮動小数点の計算は、見た目よりもずっと複雑なんです。」
生徒
「えっ?小数点を足したり引いたりするだけなのにどうしてですか?」
先生
「それにはコンピュータの仕組みが関係します。今日は浮動小数点と精度について、初心者向けにゆっくり解説していきますね。」
1. 浮動小数点とは?
C言語で小数を扱うときには、float型やdouble型を使います。これらのデータ型は、小数を保存するための仕組みとして浮動小数点という方式を使っています。浮動小数点は、十進法ではなく二進法で小数を表現します。しかし、二進法で小数を表すと、人が使う十進法ではちょうど表せる数字であっても、その値を正確に保存できないことがあります。
例えば、十進法では「0.1」はきれいな数字ですが、二進法では無限に続く数字になり、コンピュータは途中で切り捨てます。そのため、保存するときに誤差が生まれてしまうことがあります。これが浮動小数点の精度問題です。
2. C言語でよくある誤差の例を見てみよう
次のプログラムでは、小数を足し算してみます。見た目は単純ですが、結果を表示すると意外な動きをします。
#include <stdio.h>
int main(void){
double a = 0.1;
double b = 0.2;
double c = a + b;
printf("%.20f\n", c);
return 0;
}
本来、0.1と0.2を足せば「0.3」になるはずですが、実行してみると違う結果になることがあります。
0.30000000000000004441
これはC言語がおかしいわけではなく、浮動小数点の仕組み上、完全に正しい値を保存できないためです。特にプログラミング初心者が戸惑いやすいポイントなので、知っておくとエラーの原因に気づきやすくなります。
3. なぜ誤差が出るの?身近な例でイメージしよう
この誤差は、コンピュータが小数を正確に表現できないことが原因です。例えるなら、非常に細かい砂時計の砂をピンセットで正確に数えようとしているようなものです。人間から見れば「ぴったりの数字」でも、コンピュータは限られた記憶領域で保存しなければならないため、完全な精度で扱うことができません。
さらに、コンピュータが計算を重ねるほど、小さな誤差が少しずつ積み重なり、結果として大きなズレに見えることがあります。「0.1」を何回も足したつもりなのに、少しだけ違う数字になる、といった現象が起きる理由はここにあります。
4. 浮動小数点で気をつけるポイント
① 比較演算に注意する
よくある失敗として、小数を直接比較するパターンがあります。
double x = 0.1 * 3;
if(x == 0.3){
printf("同じです\n");
} else {
printf("違います\n");
}
見た目では同じように見えますが、誤差の影響で条件が「真」にならないことがあります。
このようなときは、差がごく小さいかどうかを判断する方法が一般的です。
double x = 0.1 * 3;
double y = 0.3;
double diff = x - y;
if(diff < 0.0000001 && diff > -0.0000001){
printf("ほぼ同じです\n");
}
このように誤差を許容して比較すると、浮動小数点のズレに対応できます。
② お金や精密な計算は整数で扱う方法がある
例えば「1円」や「100円」のような数は、小数ではなく整数で扱った方が安全です。「100.50」ではなく「10050」という形で、100倍にして保存する方法があります。こうすることで誤差の影響を避けられます。
5. floatとdoubleの違い
C言語には代表的な浮動小数点の型として「float」と「double」があります。floatは精度が低く、doubleは精度が高いという違いがあります。プログラムを書くときには、小さな誤差が困る計算ではdoubleを使うことが多いです。しかし、どちらを使っても誤差そのものは完全にはなくなりません。
初心者がよく混乱するのは、「doubleを使えば完全に正確になる」と思ってしまうことです。doubleはfloatよりも精度が高いですが、人間の十進法の値を二進法で正確に表せないという問題は残ります。この性質を理解しておくと、予期しない挙動に悩まされなくなります。
6. プログラムで確認してみよう
次のコードでは、floatとdoubleでどれくらい精度が違うか確認できます。
#include <stdio.h>
int main(void){
float f = 1.0f / 3.0f;
double d = 1.0 / 3.0;
printf("%.20f\n", f);
printf("%.20f\n", d);
return 0;
}
0.33333334326744079590
0.33333333333333331483
結果を比べると、doubleの方が桁が安定していることが分かります。このように、用途に合わせて適切な型を選ぶことが大切です。
7. 浮動小数点の計算で覚えておきたいこと
浮動小数点は非常に便利で、ゲーム開発、物理計算、画像処理など、さまざまな分野で利用されます。しかし、「完全に正確ではない」という特徴を理解しておくことが大切です。計算の結果が少しだけズレたとしても、ほとんどのアプリケーションでは問題になりません。ただし、金額の計算や科学計算など、誤差が許されない場面では整数を使う工夫や専用の計算手法が利用されます。
C言語の学習では、まず「浮動小数点では誤差が出ることがある」という事実を知っておくだけで十分です。プログラムが自分の予想と違う動作をしたとき、その原因が浮動小数点の誤差である可能性に気づけるようになります。