from .math_round_div_types import RoundingMode def round_div(numerator: int, denominator: int, mode: RoundingMode = "half-up") -> int: """Divide two integers, rounding according to ``mode``. Money is held in minor units (pence, cents) as integers. Every rate, discount and tax calculation eventually needs to divide, and that division is where rounding policy lives. Making it explicit here means a system can state its policy once instead of scattering ``round()`` through a codebase. """ if isinstance(numerator, bool) or isinstance(denominator, bool): raise TypeError("round_div operates on integers only") if not isinstance(numerator, int) or not isinstance(denominator, int): raise TypeError("round_div operates on integers only") if denominator == 0: raise ValueError("denominator must not be zero") negative = (numerator < 0) != (denominator < 0) n = abs(numerator) d = abs(denominator) quotient, remainder = divmod(n, d) twice = remainder * 2 if mode == "down": pass elif mode == "up": if remainder > 0: quotient += 1 elif mode == "half-even": if twice > d or (twice == d and quotient % 2 == 1): quotient += 1 elif mode == "half-up": if twice >= d: quotient += 1 else: raise ValueError('unknown rounding mode "%s"' % mode) return -quotient if negative else quotient