【C#】0.1を掛けると誤差が出る理由

— バグではなくコンピュータの仕様です —

プログラミングを学び始めると、次のような現象に出会うことがあります。

Console.WriteLine(0.1 + 0.2);

結果:

0.30000000000000004

「計算間違ってない?」

と思いますよね。

でもこれは バグではありません

コンピュータの仕組みによる必然的な結果です。

この記事では初学者向けに分かりやすく説明します。


■ まず現象を確認してみる

double x = 1.0;
double y = x * 0.1;

Console.WriteLine(y);

出力例:

0.10000000000000001

さらに:

Console.WriteLine(0.1 + 0.2 == 0.3);
False

直感と違う結果になります。


■ 原因(重要)

コンピュータは10進数で計算していない

私たちは普段

10進数

を使っていますが、コンピュータは

2進数(0と1)

で数値を保存します。


■ 0.1は2進数で正確に表現できない

10進数の

0.1

を2進数に変換すると

0.0001100110011001100110011...

無限に続きます(循環小数)。

つまり

  • メモリに収まりきらない
  • 途中で切り捨てる
  • 近似値になる
  • 計算すると誤差が出る

これは すべての言語共通の仕様 です

(C#, Java, Python, C++ など)


■ 浮動小数点という仕組み

double や float は

浮動小数点数(IEEE754)

という形式で保存されています。

ざっくり言うと:

  • 有効桁数が有限
  • 丸めが発生
  • 完全一致しない

これが誤差の正体です。


■ 実務での対処方法

✔ お金・正確さ重要 → decimal を使う

decimal a = 0.1m;
decimal b = 0.2m;

Console.WriteLine(a + b);

結果

0.3

理由:

  • decimal は10進ベース保存
  • 小数を正確に扱える

金融・会計では必須です


✔ double同士を直接比較しない

NG:

if (a == b)

OK:

if (Math.Abs(a - b) < 0.0000001)

誤差の範囲内なら一致とみなす

これはゲーム・物理・Unityでも重要です


✔ 表示だけ丸める

Console.WriteLine(value.ToString("F2"));

参考)

内部誤差は残るが見た目を整える


■ まとめ

重要ポイントは3つだけ覚えましょう

1️⃣ コンピュータは2進数で計算する

2️⃣ 0.1は2進数で正確に保存できない

3️⃣ 誤差はバグではなく仕様

そして実務では

  • 正確さ重視 → decimal
  • 計算速度重視 → double
  • 比較は誤差込み

これを使い分けます


■ 一歩進んだ学習へ

この話は次の分野に繋がります

  • 基本情報技術者試験(頻出)
  • 数値計算
  • ゲーム物理
  • シミュレーション
  • AI/機械学習

つまり

プロになるほど重要になる基礎知識 です。


■ 最後に

この現象に気付いた人はとても良い観察をしています。

プログラミングは「動いた」で終わりではなく

なぜそうなるのか

を考えた瞬間から理解が深まります。

この違和感は成長の入口です。

ぜひ実際にコードを動かして体験してみてください。

訪問数 15 回, 今日の訪問数 15回