"""Cash rounding for Canadian prices.
Since the penny was withdrawn in 2013, cash totals in Canada are rounded
to the nearest 5 cents. Card payments are not rounded.
"""
def cash_round(cents: int) -> int:
"""Return a cash total rounded to the nearest 5 cents.
Totals ending in 1, 2, 6 or 7 cents round down; totals ending in
3, 4, 8 or 9 cents round up.
Args:
cents: The total in whole cents. Must not be negative.
Returns:
The rounded total in whole cents (a multiple of 5).
Raises:
ValueError: If cents is negative.
>>> cash_round(1997)
1995
>>> cash_round(1998)
2000
"""
if cents < 0:
raise ValueError("cents must not be negative")
# Adding 2 before floor-dividing by 5 moves endings 3, 4, 8, 9
# past the next multiple of 5, so they round up; 1, 2, 6, 7 do not.
return (cents + 2) // 5 * 5
if __name__ == "__main__":
import doctest
print(doctest.testmod())
print([cash_round(c) for c in [101, 102, 103, 104, 106, 108]])
A module documented to a common industry standard: PEP 257 docstrings in Google style (Args, Returns, Raises), type hints, and a block comment that explains the one clever line. The >>> examples are doctests: doctest.testmod() runs them and checks the results, so the documentation can never quietly go out of date. Output, line by line: TestResults(failed=0, attempted=2) | [100, 100, 105, 105, 105, 110]