ZetCode

Python divmod 函数

上次修改时间:2025 年 4 月 11 日

这个全面的指南探索了 Python 的 divmod 函数,它可以同时执行除法和取模运算。我们将涵盖数字类型、实际应用和性能考量。

基本定义

divmod 函数接受两个数字,并返回一个包含它们的商和余数的元组。 它将地板除法 (//) 和取模 (%) 运算结合在一个调用中。

主要特征:适用于整数、浮点数和复数。 对于整数,它返回 (a // b, a % b)。 对于浮点数,它返回 (q, a % b),其中 q 通常是 math.floor(a / b)。

基本整数除法

这是一个简单的整数用法,展示了 divmod 如何返回除法的商和余数。

basic_divmod.py
# With positive integers
print(divmod(10, 3))   # (3, 1)
print(10 // 3, 10 % 3) # Same as above

# With negative integers
print(divmod(-10, 3))  # (-4, 2)
print(divmod(10, -3))  # (-4, -2)

这个例子展示了整数的 divmod。 元组中的第一个值是商,第二个值是余数。 请注意负数如何影响结果。

结果遵循 Python 的地板除法规则,其中商向负无穷大舍入。 余数与除数具有相同的符号。

时间转换

divmod 通常用于时间转换。 此示例将秒转换为小时、分钟和秒。

time_conversion.py
def convert_seconds(total_seconds):
    hours, remaining = divmod(total_seconds, 3600)
    minutes, seconds = divmod(remaining, 60)
    return hours, minutes, seconds

print(convert_seconds(3661))  # (1, 1, 1)
print(convert_seconds(45296)) # (12, 34, 56)

该函数首先将总秒数除以 3600 以获得小时数。 然后将余数除以 60 以获得分钟数,最后的余数为秒数。

这演示了 divmod 如何优雅地处理多步骤转换,在每一步都需要商和余数。

浮点除法

divmod 也适用于浮点数。 此示例展示了它在浮点输入下的行为。

float_divmod.py
# With positive floats
print(divmod(10.5, 3))    # (3.0, 1.5)
print(divmod(10.5, 0.5))  # (21.0, 0.0)

# With negative floats
print(divmod(-10.5, 3))   # (-4.0, 1.5)
print(divmod(10.5, -3))   # (-4.0, -1.5)

对于浮点数,divmod 返回一个浮点数作为商,以及一个使原始等式成立的余数:a = b * q + r

请注意,余数保持与除数相同的符号,类似于整数行为。 浮点精度会影响精确结果。

带有 __divmod__ 的自定义对象

您可以通过实现 __divmod__ 特殊方法,使自定义对象与 divmod 一起使用。 此示例创建了一个 Fraction 类。

custom_divmod.py
class Fraction:
    def __init__(self, numerator, denominator):
        self.n = numerator
        self.d = denominator
    
    def __divmod__(self, other):
        quotient = self.n * other.d // (self.d * other.n)
        remainder = Fraction(self.n * other.d % (self.d * other.n), self.d * other.n)
        return (quotient, remainder)
    
    def __repr__(self):
        return f"Fraction({self.n}/{self.d})"

f1 = Fraction(10, 3)
f2 = Fraction(1, 2)
print(divmod(f1, f2))  # (6, Fraction(2/6))

Fraction 类实现 __divmod__ 以返回商(整数)和余数 (Fraction)。 当我们在 Fraction 实例上调用 divmod 时,Python 会使用此方法。

这种模式对于余数除法有意义的数学类(多项式、向量等)很有用。

错误处理

divmod 函数在遇到不支持的类型或除以零时会引发错误。 此示例展示了正确的错误处理。

errors.py
try:
    print(divmod("10", 3))
except TypeError as e:
    print(f"Error: {e}")  # unsupported operand type(s) for divmod(): 'str' and 'int'

try:
    print(divmod(10, 0))
except ZeroDivisionError as e:
    print(f"Error: {e}")  # integer division or modulo by zero

这些示例演示了 divmod 在无效输入下的行为。 字符串和除以零会引发适当的异常。

要使类与 divmod 一起使用,请如上一个示例所示实现 __divmod__

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程