Python3 divmod()(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在 Python 编程中,数学运算始终是开发者需要掌握的核心技能之一。无论是处理时间、分页逻辑,还是进行复杂的数学建模,开发者经常会遇到需要同时获取两个数的商和余数的场景。这时,一个名为 divmod() 的函数就能派上用场。它能以简洁的方式完成这一操作,帮助开发者提升代码的可读性和效率。

本文将从零开始讲解 divmod() 函数的原理、语法、用法,通过生动的比喻和实际案例,帮助编程初学者和中级开发者快速掌握这一工具,并理解其在真实开发中的应用场景。


什么是 divmod() 函数?

divmod() 是 Python 内置的数学函数,其名称来源于 division(除法)和 modulus(取余)的组合。它的核心功能是 同时返回两个数的商和余数

可以将 divmod() 想象为一个“数学助手”:当你要计算两个数的除法时,它不仅能告诉你“商是多少”,还能直接给出“余数是多少”,而无需分别调用 /% 运算符。

形象比喻:分蛋糕的数学问题

假设你有一块蛋糕,需要将其分给若干人。例如,有 13 块蛋糕,要分给 4 个人:

  • 是每个人能获得的蛋糕数量(即 13 // 4 = 3);
  • 余数是分完后剩下的蛋糕数量(即 13 % 4 = 1)。

divmod() 就像一个“分蛋糕计算器”,直接返回 (3, 1),避免了两次独立计算的麻烦。


基本语法与参数解析

函数语法

divmod(a, b)  
  • 参数

    • a(被除数):可以是整数或浮点数。
    • b(除数):同上,但不能为 0(否则会抛出 ZeroDivisionError)。
  • 返回值
    一个包含两个元素的元组 (商, 余数),其中:

    • 商是 a // b 的结果(向下取整的除法);
    • 余数是 a % b 的结果。

关键点说明

  1. 整数与浮点数的区别

    • ab 均为整数,则商是整数除法结果,余数是整数。
    • 若其中任意一个为浮点数,则商和余数均为浮点数。
  2. 负数的处理
    Python 的除法遵循“向负无穷方向取整”的规则。例如:

    divmod(-13, 4) → (-4, 3)  
    

    这是因为 -13 // 4 = -4,而 -4 * 4 = -16,因此余数为 -13 - (-16) = 3


基础用法示例

示例 1:整数除法

result = divmod(13, 4)  
print(result)  # 输出:(3, 1)  

quotient, remainder = divmod(13, 4)  
print(f"商:{quotient}, 余数:{remainder}")  

示例 2:浮点数除法

result = divmod(10.5, 3)  
print(result)  # 输出:(3.0, 1.5)  

示例 3:负数处理

print(divmod(-13, 4))  # 输出:(-4, 3)  

print(divmod(13, -4))  # 输出:(-4, -3)  

进阶用法与常见场景

场景 1:时间转换

将秒数转换为“分钟:秒”格式:

seconds = 150  
minutes, remaining_seconds = divmod(seconds, 60)  
print(f"{minutes} 分 {remaining_seconds} 秒")  # 输出:2 分 30 秒  

场景 2:分页逻辑

假设每页显示 10 条数据,计算总页数和最后一页的条目数:

total_items = 27  
page_size = 10  
pages, last_page_items = divmod(total_items, page_size)  
if last_page_items != 0:  
    pages += 1  
print(f"总页数:{pages}, 最后一页条目数:{last_page_items}")  

场景 3:数学问题

计算多项式展开中的余数:

def polynomial(x):  
    return x**3 + 2*x**2 + 3*x + 4  

def horner(coeffs, x):  
    result = 0  
    for coeff in coeffs:  
        result = divmod(result * x + coeff, 1)[0]  
    return result  

coefficients = [1, 2, 3, 4]  # 对应 x^3 + 2x^2 + 3x +4  
print(horner(coefficients, 5))  # 输出:174(与 polynomial(5) 结果一致)  

divmod() 的底层原理与注意事项

原理解析:数学公式

divmod(a, b) 的数学定义为:

商 = a // b  
余数 = a - (商 * b)  

因此,余数的符号始终与除数 b 的符号一致。

注意事项

  1. 除数不能为零

    divmod(10, 0)  # 抛出 ZeroDivisionError  
    
  2. 浮点数精度问题
    浮点数运算可能因精度丢失导致余数不准确。例如:

    print(divmod(0.3, 0.1))  # 可能输出 (2.0, 0.0),但实际 0.1 * 2 = 0.2,余数应为 0.1  
    

    这是因为 0.30.1 在二进制中无法精确表示。

  3. 与手动计算的对比
    手动计算商和余数时,需确保两者的计算基于相同的除法规则(如 //% 的结合性)。而 divmod() 内置了这一规则,避免了人为错误。


与其他函数的对比

与手动计算的对比

a, b = 13, 4  
quotient = a // b  
remainder = a % b  
print((quotient, remainder))  # 输出:(3, 1)  

print(divmod(a, b))  # 输出相同结果  

divmod() 的优势在于代码简洁性,尤其在需要同时使用商和余数时。

与 math.floor() 的对比

虽然 math.floor(a / b) 可以计算商,但 divmod() 的优势在于 一次性返回两个结果,避免重复计算。


常见问题解答

Q1:为什么余数的符号与除数一致?

A:这是 Python 的设计规则。例如,divmod(-13, 4) 的余数为 3,因为 -4 * 4 = -16,而 -13 - (-16) = 3。这种设计确保了数学一致性。

Q2:如何避免浮点数精度问题?

A:在需要高精度计算时,建议使用 decimal 模块,或转为整数运算后还原。例如:

from decimal import Decimal  

a = Decimal('0.3')  
b = Decimal('0.1')  
print(divmod(a, b))  # 输出:(3, Decimal('0'))  

Q3:divmod() 是否支持复数?

A:不支持。复数的除法和取余规则在数学上未明确定义,因此 Python 禁止对复数使用 divmod()


实战案例:实现进制转换

案例:十进制转二进制

def decimal_to_binary(n):  
    if n == 0:  
        return "0"  
    bits = []  
    while n > 0:  
        quotient, remainder = divmod(n, 2)  
        bits.append(str(remainder))  
        n = quotient  
    return ''.join(reversed(bits))  

print(decimal_to_binary(13))  # 输出:1101  

解析:通过不断将数字除以 2,余数即为二进制的每一位。


结论

divmod() 是 Python 中一个简单但功能强大的工具,能够帮助开发者高效地处理商和余数的计算。通过本文的讲解,读者应能掌握其基本语法、进阶用法以及在时间转换、分页逻辑等场景中的应用。

无论是编程新手还是有一定经验的开发者,理解 divmod() 的原理和适用场景,都能让你的代码更简洁、更高效。建议在实际项目中尝试替换手动计算的场景,感受其带来的便利性。

掌握 divmod() 仅仅是 Python 数学函数学习的开始,后续可以探索 mathnumpy 等模块,逐步构建更强大的数学运算能力。

最新发布