Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Financial calculations: double or decimal? [duplicate]

Tags:

c#

.net

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.

like image 508
Marcel Avatar asked Nov 28 '22 19:11

Marcel


1 Answers

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.

like image 101
Rob Avatar answered Dec 09 '22 18:12

Rob