Given a rational number, I need to get the nearest integer, with exact halves rounded up (that is, towards positive infinity). The results must be exact, which rules out float
and Decimal
, both of which have finite precision.
The following code works perfectly in all cases except for negative numbers:
def roundhalfup(x: Fraction) -> int:
"Returns the closest integer to x, with exact ties rounded up"
#assert not x < 0, ValueError("Negative numbers not implemented")
return int(x + Fraction(1, 2))
def divroundhalfup(a: int | Fraction, b: int | Fraction) -> int:
return roundhalfup(Fraction(a, b))
For instance, it succeeds on:
But it fails on
I know this could be kludged by using Decimal
with ROUND_HALF_UP
and decimal.getcontext().prec=99999
, but I'd like to avoid such an ugly hack if possible. How can this be done without any rounding -- purely integrally?
In roundhalfup
, replace int(...)
with math.floor(...)
:
from math import floor
def roundhalfup(x: Fraction) -> int:
"""
Returns the closest integer to x, with exact ties rounded up.
"""
return floor(x + Fraction(1, 2))