2

I am doing a simple calculation in VB.Net, following is the code.

Dim total As String = "192.04"
Dim paid As String = "200"
Dim change As String = "7.96"
'//This prints -7.99360577730113E-15 (Incorrect)
MsgBox((CDbl(total) - CDbl(paid)) + CDbl(change))

The answer I expect from this calculation is 0 but I get -7.99360577730113E-15. I don't know the exact reason for this, I couldn't quite understand the reason explained on MSDN. Any clarification would be really helpful.

And I did a Math.Round to 2 decimal places & the problem was solved, therefore do I need to use Math.Round everywhere I do a calculation with decimals ?

codeGEN
  • 686
  • 2
  • 18
  • 45

2 Answers2

3

That's because of how double (or floating point numbers in general) is represented in memory. You should use decimal for financial calculations instead of double:

double total = 192.04;
double paid = 200;
double change = 7.96;

double result = (total - paid) + change;   // -7.99360577730113E-15
decimal total = 192.04m;
decimal paid = 200m;
decimal change = 7.96m;

decimal result = (total - paid) + change;   // 0.00

I know it's C#, but you should see the difference anyway.

You can use Decimal.Parse to get a decimal from string:

Dim total As String = "192.04"
Dim paid As String = "200"
Dim change As String = "7.96"

MsgBox((Decimal.Parse(total) - Decimal.Parse(paid)) + Decimal.Parse(change))
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • Thanks for the answer. I know this is out of the scope of the question, but why did you use Decimal.Parse without CDec. – codeGEN Aug 24 '14 at 05:24
  • `CDec` is VB.NET specific thing. It will work not just for `string`s, but also for other types. `Decimal.Parse` is .NET Framework method which only accepts `string`s. You will be able to use it not only from VB.NET but also from C#, F# and other .NET Framework languages. I prefer the latter. – MarcinJuraszek Aug 24 '14 at 05:33
2

This precision error is due to the way floating point numbers work in computers (more specifically the IEEE standard, see WikiPedia). In short, floating point numbers are stored as "binary numbers with decimal points" then raised to some power of 2. Therefore it cannot store exact decimal digits. This problem is common to all programming languages and not just .NET alone.

To overcome this problem, the Decimal type is used when calculating payments that require base 10 precision. Outside of .NET, almost all modern programming environments also provide this variable type.

kevin
  • 2,196
  • 1
  • 20
  • 24