• システム開発に関わる内容をざっくりと書いていく

金額計算にdoubleを使ってはいけない理由

金額や通貨の計算でdoubleを使うのはNG。理由は、浮動小数点演算による丸め誤差が発生するから。doubleは数値を2進数で表現するため、一部の10進数(例: 0.1や0.2)を正確に表現できない。これが累積すると、金額計算のような正確さが求められる場面で問題が出る。


浮動小数点数の誤差とは?

double型は浮動小数点数を扱うため、大きな範囲の数値を効率的に扱えるが、正確性には限界がある。たとえば、0.1は2進数で無限小数になるため、double型に格納すると誤差が生じる。


プログラム例(C#)

次の例では、商品単価を0.1円、商品数を10個として合計金額を計算する。

csharp
using System;

class Program
{
static void Main()
{
double pricePerItem = 0.1; // 商品単価
int itemCount = 10; // 商品数
double total = 0.0;

for (int i = 0; i < itemCount; i++)
{
total += pricePerItem; // 合計金額を加算
}

Console.WriteLine($"期待する合計金額: {pricePerItem * itemCount}"); // 正しい合計金額
Console.WriteLine($"実際の合計金額: {total}"); // 計算結果
}
}

実行結果

期待する合計金額: 1.0
実際の合計金額: 0.9999999999999999

小数点以下で誤差が発生し、合計金額がズレる。金額計算では許容できない問題。


解決策:decimal型を使う

金額や通貨の計算にはdecimal型を使うべき。decimalは固定小数点数を扱うため、10進数での正確な計算が可能。


修正版プログラム例

csharp
using System;

class Program
{
static void Main()
{
decimal pricePerItem = 0.1m; // 商品単価 (mでdecimal指定)
int itemCount = 10; // 商品数
decimal total = 0.0m;

for (int i = 0; i < itemCount; i++)
{
total += pricePerItem; // 合計金額を加算
}

Console.WriteLine($"期待する合計金額: {pricePerItem * itemCount}"); // 正しい合計金額
Console.WriteLine($"実際の合計金額: {total}"); // 計算結果
}
}

実行結果

期待する合計金額: 1.0
実際の合計金額: 1.0

誤差が解消され、正確な結果を得られる。


doubledecimalの違い

特徴doubledecimal
精度丸め誤差が発生する正確な数値表現
用途科学計算、大きな数値範囲金額、通貨、財務計算
速度高速やや遅い

まとめ

金額や通貨計算では、正確さが最優先。浮動小数点数のdoubleではなく、decimal型を使うことが鉄則。誤差を放置すると、最終的に大きなトラブルにつながる可能性がある。