-1

I am getting unpredictable behavior of decimal in C#.NET. Here is the code snippet

decimal num1 = 2474M;
decimal num2 = 4947M;
decimal num3 = 4947M;
decimal sum = num1 + num2 + num3;

decimal perDouble1 = num1 / sum ;
decimal perDouble2 = num2 / sum ;
decimal perDouble3 = num3 / sum ;
decimal sumDouble = perDouble1 + perDouble2 + perDouble3;

Output: 1.0000000000000000000000000001M

If I change the numbers as

decimal num1 = 2474M;
decimal num2 = 4946M;
decimal num3 = 4947M;

Output as: 1.0000000000000000000000000000M

How I can avoid this?

  • 4
    What is your problem exactly ? – aloisdg Jan 08 '15 at 14:32
  • 7
    Note from [MSDN](http://msdn.microsoft.com/en-us/library/system.decimal%28v=vs.110%29.aspx): `The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding.` – Matt Burland Jan 08 '15 at 14:33
  • As to how to avoid it, round your result. You probably don't need 28 decimal places of precision, so round it to something sensible. – Matt Burland Jan 08 '15 at 14:36
  • Use some kind of Rational or Fraction type that consists of two `BigInteger`s. – CodesInChaos Jan 08 '15 at 16:47
  • possible duplicate of [(.1f+.2f==.3f) != (.1f+.2f).Equals(.3f) Why?](http://stackoverflow.com/questions/15117037/1f-2f-3f-1f-2f-equals-3f-why) – Peter Duniho Jan 08 '15 at 20:38

1 Answers1

0

Everything is fine!

It is not unpredictable, type decimal is an approximation ( IEEE 754: 128bit )

One way around this would be to use BigNum class. Problem with that is, that .net does not have 1. It does have BigInteger (System.Numerics), but it does not have BigDecimal. If you want 1, then typically you would use GNU GMP, but I do not think there exists a C# version.

However with 0 effort you can find GMP c# wrapper in beta.

Margus
  • 19,694
  • 14
  • 55
  • 103