1

I got confusing with the result of round() with 2 decimal places

a = 1352.845
res = round(a, 2)
=> 1352.85 (Right as I expected)

b = 578.005
res = round(b, 2)
=> 578.0 (Wrong, It would be 578.01 instead of 578.0)

what happens with case b or Have I misunderstood anything?

Answer:

from decimal import Decimal, ROUND_UP

Decimal('578.005').quantize(Decimal('.01'), rounding=ROUND_UP)

Because it needs to be used for monetary so the default convention of python round() (Banker's Rounding) doesn't right in my case

Phong Vy
  • 369
  • 5
  • 19

3 Answers3

2

While it can be confusing, this is due to the fact that most decimal fractions cannot be represented exactly as a float type.

For further reference, see: https://docs.python.org/3/tutorial/floatingpoint.html#tut-fp-issues

Wes Doyle
  • 2,199
  • 3
  • 17
  • 32
2

It is not wrong actually.
It is Banker's Rounding and is an implementation detail on purpose.

If you wish to retain the 'always round 0.5 up' method, you can do so by doing:

import decimal
#The rounding you are looking for
decimal.Decimal('3.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
>>> Decimal('4')
decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
>>> Decimal('3')


#Other kinds of rounding
decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_EVEN)
>>> Decimal('2')

decimal.Decimal('3.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_DOWN)
>>> Decimal('3')
ycx
  • 3,155
  • 3
  • 14
  • 26
  • Banker's rounding (a.k.a. "round ties to even") isn't relevant here, because the values that the OP is rounding are _not_ ties. Note that `1352.845` is rounding _up_, not down as you might expect from Banker's Rounding. That's because the actual value stored here is `1352.845000000000027284841053187847137451171875`; that value is fractionally closer to 1352.85 than to 1352.84, so it rounds up. – Mark Dickinson Dec 17 '18 at 19:39
0

Recall your Physics / Mathematics lesson where they taught how rounding off works.

If the last digit is a '5' and you round that off, it's preceding digit shall move to the next even digit if it is odd but shall remain the same if it is already even.

Rachit Bhargava
  • 170
  • 1
  • 12
  • That's not true. What you are describing is Bankers' Rounding and is by no means the standard for many use cases – ycx Dec 17 '18 at 05:22
  • Well, that is considered to be the standard in many countries (India included) when it comes to scientific calculations. Also, Python's `round` function seem to be following this convention. – Rachit Bhargava Dec 17 '18 at 05:28