Skip to content
The Lumenary

Math laboratory

Exactly one quotient and remainder

Divides by repeated subtraction, lists all pairs (q, r) with a = q x b + r, and checks by exhaustive search that for every a <= 500 and 1 <= b <= 12 exactly one pair has 0 <= r < b, agreeing with divmod. This is a complete check of those 6,012 cases only; the lesson proves it for all numbers.

Back to the labExhaustive finite checkExact computation
Exactly one quotient and remainderPythonExhaustive finite checkExact computationComputationally tested
"""Division with remainder: one quotient and one remainder, found by search.

For a = q x b + r there are many pairs (q, r) if r may be as large as we like,
but exactly one with 0 <= r < b. We find the answer for 347 eggs in trays of 30
by repeated subtraction, list every pair that would work without the rule
r < b, and then search exhaustively: for every a up to 500 and b from 1 to 12
there is exactly one pair with r < b, and it agrees with Python's divmod.
Finally we see that "5 divided by 0" has no candidate answer at all.
"""

def repeated_subtraction(a, b):
    """Take b away from a as often as possible; return (quotient, remainder)."""
    if b <= 0:
        raise ValueError("b must be positive")
    if a < 0:
        raise ValueError("a must be a whole number")
    q = 0
    while a >= b:
        a -= b
        q += 1
    return q, a

def all_pairs(a, b, small_remainder=True):
    """Every (q, r) of whole numbers with q*b + r == a (and r < b if asked)."""
    if b <= 0:
        raise ValueError("b must be positive")
    pairs = []
    for q in range(a // b + 1):
        r = a - q * b
        if r >= 0 and (r < b or not small_remainder):
            pairs.append((q, r))
    return pairs

def exhaustive_check(max_a, max_b):
    """Return (cases, all unique?, all agree with divmod?)."""
    cases, unique, agree = 0, True, True
    for a in range(max_a + 1):
        for b in range(1, max_b + 1):
            cases += 1
            pairs = all_pairs(a, b)
            unique = unique and len(pairs) == 1
            agree = agree and pairs == [divmod(a, b)]
    return cases, unique, agree

def solutions_of_times_zero(target, search_up_to):
    """All q in 0..search_up_to with q * 0 == target."""
    return [q for q in range(search_up_to + 1) if q * 0 == target]

def main():
    q, r = repeated_subtraction(347, 30)
    print(f"347 eggs, trays of 30: take away 30 a total of {q} times,"
          f" {r} eggs left.")
    print(f"  347 = {q} x 30 + {r}, and {r} < 30")
    loose = all_pairs(347, 30, small_remainder=False)
    shown = ", ".join(f"({a}, {b})" for a, b in loose[:4])
    print(f"Without the rule r < 30 there are {len(loose)} pairs (q, r):")
    print(f"  {shown}, ..., {loose[-1]}")
    print(f"With the rule r < 30 there is only {all_pairs(347, 30)}")
    print()
    cases, unique, agree = exhaustive_check(500, 12)
    print(f"Every a from 0 to 500 and b from 1 to 12 ({cases:,} cases):")
    print(f"  exactly one pair with r < b every time: {unique}")
    print(f"  that pair is Python's divmod(a, b) every time: {agree}")
    print()
    print("Dividing by zero: q x 0 = 5 for q in 0..1000? "
          f"{len(solutions_of_times_zero(5, 1000))} solutions.")
    print("  q x 0 = 0 for q in 0..1000? "
          f"{len(solutions_of_times_zero(0, 1000))} solutions: every q works.")
    print()
    print("Epistemic status: the search is complete for the 6,012 cases it")
    print("checks, so uniqueness is certain there and nowhere else. The lesson's")
    print("argument (multiples of b are b apart) proves it for every a and b > 0.")
    print("The zero search is evidence; q x 0 = 0 for every q is the proof.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Used in