要学习的知识点
- 二、八、十六进制
- 除基取余
- 余数逆序
- divmod()
- 字符串连接与反向迭代
题目
练习 16:将十进制非负整数转换为二进制、八进制和十六进制。
转换过程通过反复除基数实现,不调用内置进制格式化函数。
完整代码
以下内容与 ex16.py 一致,可对照右侧讲解阅读。
"""练习 16:将十进制非负整数转换为二进制、八进制和十六进制。
转换过程通过反复除基数实现,不调用内置进制格式化函数。
学习说明:
- convert_to_base(number, base) 是转换函数;digits 字符串提供 0 到 15 的数字符号。
- 每次除以 base,余数就是当前最低位;继续处理商,直到商为 0。
- 余数是从低位到高位得到的,所以最后需要 reversed() 倒转顺序。
- 0 要单独处理,否则循环不会运行且结果列表为空。
"""
def convert_to_base(number, base):
digits = "0123456789ABCDEF"
if number == 0:
return "0"
# 先按从低位到高位收集每次除法得到的余数。
result = []
while number > 0:
number, remainder = divmod(number, base)
result.append(digits[remainder])
return "".join(reversed(result))
number = int(input())
if number < 0:
raise ValueError("请输入非负整数")
print("binary:", convert_to_base(number, 2))
print("octal:", convert_to_base(number, 8))
print("hexadecimal:", convert_to_base(number, 16))
进阶写法
这版与初学版解决同一道题,使用更精炼的语法或标准库工具。
进阶源码:ex16_adv.py
"""练习 16 进阶版:用 format 的进制格式符直接转换整数。"""
number = int(input())
if number < 0:
raise ValueError("请输入非负整数")
print("binary:", format(number, "b"))
print("octal:", format(number, "o"))
print("hexadecimal:", format(number, "X"))
format(number, 'b'/'o'/'X') 直接返回二、八、十六进制文本;X 表示大写十六进制,不包含 0x 前缀。
运行结果
示例输入:
26程序输出:
binary: 11010
octal: 32
hexadecimal: 1A逐个认识函数
下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。
| 函数形式 | 功能与返回值 | 注意事项 |
|---|---|---|
separator.join(iterable) | 用 separator 将多个字符串连接成一个新字符串。 | 每一项都必须是字符串;空字符串作为分隔符时不会插入字符。 |
ValueError(message) | 内置异常类型,用来表示参数值不符合要求。 | raise ValueError(...) 会立即抛错并停止当前程序流程。 |
convert_to_base(number, base) | 本题自定义函数:返回非负整数在目标进制下的字符串。 | 通过 divmod 取余;收集数字后需要逆序。 |
divmod(a, b) | 返回二元组 (a // b, a % b),即商和余数。 | 除数 b 不能为 0。 |
input(prompt='') | 读取一行文本,返回 str;若提供 prompt 会先显示提示。 | 返回值默认是字符串,计算前通常要做类型转换。 |
int(value, base=10) | 把整数文本或数值转换为整数。 | int('3.5') 不合法;按指定进制解析时可传 base。 |
print(*objects, sep=' ', end='\n') | 把对象转换为文本显示;返回 None。 | 默认空格分隔并在末尾换行。 |
list.append(item) | 在列表末尾追加一个元素;返回 None。 | 会原地修改列表。 |
reversed(sequence) | 返回反向迭代器,不修改原序列。 | 可配合 ''.join() 逆序拼接字符。 |
自定义函数 to_base
def convert_to_base(number, base):| 项目 | 说明 |
|---|---|
| 参数 number | 要转换的十进制非负整数。 |
| 参数 base | 目标基数。本题使用 2、8、16。 |
| 返回值 | 表示转换结果的字符串,例如 "11010" 或 "1A"。 |
| 边界 | number 为 0 时直接返回 "0",因为 0 没有非零位可供循环收集。 |
函数通过 divmod(number, base) 同时得到商和余数。余数对应当前最低位,使用 DIGITS[remainder] 找到对应符号,然后把商作为下一轮的 number。
相关函数与方法
| 写法 | 参数 / 返回 | 说明 |
|---|---|---|
divmod(a, b) | 返回 (a//b, a%b) 的二元组。 | 每轮取得下一位余数和待处理的商。 |
list.append(value) | 在列表末尾添加一项,返回 None。 | 余数从低位开始加入 result。 |
reversed(iterable) | 返回反向迭代器,不会改动原容器。 | 把低位到高位的字符倒过来读取。 |
"".join(iterable) | 字符串方法;把多个字符串连接成一个字符串并返回。 | 空字符串作为分隔符,因此字符之间不会插入额外内容。 |
int(input()) | 读取并转换十进制整数。 | 程序只接受非负数;负数将引发 ValueError。 |
十六进制的数字表
十六进制需要 16 个符号:0–9 表示 0–9,A–F 表示 10–15。代码字符串 "0123456789ABCDEF" 用下标查符号,所以 remainder=10 时取到 A。
试试把 0、1、15、16、26 分别转换成 2、8、16 进制。特别检查 0 和出现 A–F 的值。
代码如何运行
- 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
- 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
- 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。
先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。
自己动手试一试
测试 0、15、16、26;检查十六进制 A–F,以及 0 的特殊处理。
先在 lx16.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。