Financial calculations: double or decimal?

  • A+
Category:Languages

We are working with financial calculations. I found this post about storing money values as decimals: decimal vs double! - Which one should I use and when?

So I'm storing amount as decimals.

I have the following calculation: 12.000 * (1/12) = 1.000

If I use a decimal data type for storing the amount and the result amount I not get the expected result

// First approach:     decimal ratio = 1m / 12m; decimal amount = 12000; decimal ratioAmount = amount * ratio; ratioAmount = 999.9999999999999  // Second approach: double ratio = 1d / 12d; decimal amount = 12000; decimal ratioAmount = (decimal)((double)amount * ratio); ratioAmount = 1.000  // Third approach: double ratio = 1d / 12d; double amount = 12000; double ratioAmount = amount * ratio; ratioAmount = 1.000 

What is the best way? Everyone is talking about that amounts/money must be stored as decimals.

 


Never, ever, ever, ever store financial amounts in a double. Here's an example from my blog that shows why double shouldn't be used:

var lineValues = new List<double> { 1675.89, 2600.21, 5879.79, 5367.51, 8090.30, 492.97, 7888.60 }; double dblAvailable = 31995.27d; double dblTotal = 0d;  foreach (var lineValue in lineValues) {     dblTotal += lineValue; }  if (dblAvailable < dblTotal) {     Console.WriteLine("They don't add up!"); } 

You'll see that the Console.WriteLine will be hit because the doubles actually add up to 31995.270000000004. As you may be able to guess from the names of the variables, this code example was based on some actual code in a finance system - this issue caused users to not be able to correctly allocate amounts to transactions.

Adding the numbers up as decimals with this additional code:

decimal decAvailable = (decimal)dblAvailable; decimal decTotal = (decimal)dblTotal;  if (decAvailable < decTotal) {     Console.WriteLine("They still don't add up!"); } 

Won't hit the Console.WriteLine. The moral of the story: use decimal for financial calculations!

The very first part of the language reference for the decimal keyword states:

Compared to other floating-point types, the decimal type has more precision and a smaller range, which makes it appropriate for financial and monetary calculations.

It's also worthy of note that for a numeric literal to be treated as a decimal, the suffix m (for money) should be used, further pointing towards the appropriateness of the type for financial data.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: