Don't store monetary values as doubles

Everyone should know that you shouldn't store monetary values as doubles, but I guess everyone doesn't!

It's something that everyone should know, but apparently not...

I had an issue raised by a user recently for a piece of software that I inherited where they were being told that EUR 31,995.27 was more than EUR 31,995.27 when trying to complete a transaction. Digging in, I discovered that the developer who'd originally written the code was storing the values received as doubles. This is a really, really, bad idea. If you run the following code:

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 end up with output of They don't add up!, because when looking at the value in dblTotal in the debugger the value is actually 31995.270000000004, which is most definitely not less than 31995.27. Tack this bit of code on the end:

decimal decAvailable = (decimal)dblAvailable;
decimal decTotal = (decimal)dblTotal;

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

And you won't hit the second They don't add up! because the tiny, tiny fraction that causes the mis-match goes away!

The moral of the story is: Please, please, please, PLEASE don't use double to represent monetary values. Use decimal.

About Rob

I've been interested in computing since the day my Dad purchased his first business PC (an Amstrad PC 1640 for anyone interested) which introduced me to MS-DOS batch programming and BASIC.

My skillset has matured somewhat since then, which you'll probably see from the posts here. You can read a bit more about me on the about page of the site, or check out some of the other posts on my areas of interest.

No Comments

Add a Comment