3

AFAIK .NET's default round option is to even, so Math.Round(1.225,2) should give 1.22 but it gives 1.23.

Math.Round(2.225,2) = 2.22 
Math.Round(100.225,2) = 100.22 

all the values I tried rounds to nearest even but only 1.225 and -1.225 rounds to 1.23 and -1.23.

  • 3
    Your title and the content of your question conflict with each other. Specifcally your title is correct and the first sentence in your content is wrong `Math.Round(1.225,2)` will give `1.23`. – juharr Jan 15 '16 at 12:50
  • @juharr good catch. Corrected the content. – user2560178 Jan 15 '16 at 12:58
  • 1
    @Luaan I was just pointing out the literal conflict between what the OP put in the title and the first sentence. Based on that code alone it's only using the `Math.Round(Double,Int32)` overload. – juharr Jan 15 '16 at 12:58
  • @juharr Yes, I'm talking about the case with double. With decimal there is no problem. – user2560178 Jan 15 '16 at 12:59
  • 3
    So this is actually more a duplicate of [Is floating point math broken?](http://stackoverflow.com/q/588004/216074) – poke Jan 15 '16 at 13:01
  • @Luaan Also how is this a dup. The OP expects 1.225 to become 1.22 not 1.23. The dup is asking why 2.5 isn't rounded up to 3. The OP's question is more of why is this one case rounded up when it shouldn't be. – juharr Jan 15 '16 at 13:02
  • @luaan I don't think this is a duplicate question. 1.225 is not rounded to nearest even, which I think is an exceptional case. I'm trying to learn the reason for that. – user2560178 Jan 15 '16 at 13:03
  • @user2560178 I agree it's not a duplicate, but the answer is in Luaan's comment. The actual representation of 1.225 as a `double` is actually slightly more than 1.225 and thus rounds up whereas the other examples you gave either can be exactly represented as a `double` or have values that are slightly less when represented as a `double`. – juharr Jan 15 '16 at 13:07
  • 4
    The double `1.225` is actually `1.225000000000000088817841970012523233890533447265625`, which is larger than the the middle point, so it is rounded up. – poke Jan 15 '16 at 13:08
  • You're right, it's more like a duplicate of two separate questions. Rescinded :) – Luaan Jan 15 '16 at 13:12
  • @poke thanks, that was the answer i was looking for. – user2560178 Jan 15 '16 at 13:17

2 Answers2

7

The main problem is that in float and double, the amount of decimal places is not part of the value, and the precision isn't decimal, but rather, binary. And there's no finite binary number that can represent 1.225 exactly.

So when you do Math.Round(1.225f, 2), you're actually doing something more like Math.Round(1.22500002f, 2) - there's no midpoint rounding involved.

The same problem appears with Math.Round(2.225f, 2) - it's just that the "real" value is slightly smaller than 2.225f, so the result rounds down. But there's still no midpoint rounding involved.

If you need decimal precision, use decimal. Neither float nor double are designed for decimal precision - they're fine for e.g. physics calculations, but not for e.g. accounting.

Luaan
  • 62,244
  • 7
  • 97
  • 116
2

1.225 can't be represented exactly in floating point, so you're really rounding 1.225000023841858.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760