要学习的知识点
- 二、八、十、十六进制互转
- int(text, base) 解析
- 自定义进制转换函数
- 除基取余
- 字符表与结果逆序
题目
补充练习:在二、八、十、十六进制之间进行任意方向转换。
输入:数值字符串(十六进制可用 A-F)、原进制、目标进制;进制均为 2、8、10、16。
完整代码
以下内容与 ex22.py 一致,可对照右侧讲解阅读。
"""补充练习:在二、八、十、十六进制之间进行任意方向转换。
输入:数值字符串(十六进制可用 A-F)、原进制、目标进制;进制均为 2、8、10、16。
学习说明:
- to_base() 将非负十进制整数转成目标进制;divmod() 每次给出商和余数。
- 余数对应当前最低位,因此收集后要倒序;数字字母表支持十六进制的 A 到 F。
- int(text, source_base) 是 Python 提供的输入解析方式,先把原进制数值转成整数。
- 转换到目标进制时调用自己写的 to_base(),练习“除基取余”算法。
"""
DIGITS = "0123456789ABCDEF"
def to_base(number, base):
# 用字符表把余数 0~15 转换成相应的数字符号。
if number == 0:
return "0"
result = []
while number:
number, remainder = divmod(number, base)
result.append(DIGITS[remainder])
return "".join(reversed(result))
text = input().strip()
source_base, target_base = map(int, input().split())
valid_bases = {2, 8, 10, 16}
if source_base not in valid_bases or target_base not in valid_bases:
raise ValueError("进制只能是 2、8、10 或 16")
value = int(text, source_base)
if value < 0:
raise ValueError("本练习只处理非负整数")
print(to_base(value, target_base))
进阶写法
这版与初学版解决同一道题,使用更精炼的语法或标准库工具。
进阶源码:ex22_adv.py
"""练习 22 进阶版:使用 int 的进制解析和 format 格式化转换。"""
text = input().strip()
source_base, target_base = map(int, input().split())
if source_base not in {2, 8, 10, 16} or target_base not in {2, 8, 10, 16}:
raise ValueError("进制只能是 2、8、10 或 16")
number = int(text, source_base)
if number < 0:
raise ValueError("本练习只处理非负整数")
format_codes = {2: "b", 8: "o", 10: "d", 16: "X"}
print(format(number, format_codes[target_base]))
int(text, base) 按原进制解析;字典把目标进制映射到 format() 的格式符,避免自己编写除基取余转换。
运行结果
示例输入:
FF
16 2程序输出:
11111111逐个认识函数
下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。
| 函数形式 | 功能与返回值 | 注意事项 |
|---|---|---|
separator.join(iterable) | 用 separator 将多个字符串连接成一个新字符串。 | 每一项都必须是字符串;空字符串作为分隔符时不会插入字符。 |
ValueError(message) | 内置异常类型,用来表示参数值不符合要求。 | raise ValueError(...) 会立即抛错并停止当前程序流程。 |
divmod(a, b) | 返回二元组 (a // b, a % b),即商和余数。 | 除数 b 不能为 0。 |
input(prompt='') | 读取一行文本,返回 str;若提供 prompt 会先显示提示。 | 返回值默认是字符串,计算前通常要做类型转换。 |
str.split(sep=None) | 按分隔符拆分字符串,返回字符串列表。 | 默认按连续空白拆分并忽略首尾空白。 |
str.strip(chars=None) | 返回去掉首尾空白或指定字符的新字符串。 | 不会删除字符串中间的字符。 |
int(value, base=10) | 把整数文本或数值转换为整数。 | int('3.5') 不合法;按指定进制解析时可传 base。 |
map(function, iterable) | 逐个应用函数,返回惰性迭代器。 | 常与 list() 一起使用以立即取得结果。 |
print(*objects, sep=' ', end='\n') | 把对象转换为文本显示;返回 None。 | 默认空格分隔并在末尾换行。 |
list.append(item) | 在列表末尾追加一个元素;返回 None。 | 会原地修改列表。 |
reversed(sequence) | 返回反向迭代器,不修改原序列。 | 可配合 ''.join() 逆序拼接字符。 |
to_base(number, base) | 本题自定义函数:把非负十进制整数转换为目标进制字符串。 | 基数需与函数支持的字符表范围相符。 |
两阶段转换
- 检查原进制和目标进制都属于 {2, 8, 10, 16}。
int(text, source_base)把输入文本解释成整数,例如 int("FF",16) 得 255。- 把十进制整数交给 to_base(number, base)。
- to_base 反复除以目标进制,收集余数,倒序拼成字符串。
十进制在此只是程序内部的统一数值表示。Python 的 int 与进制无关;整数文本前缀或传入 base 才说明如何解析文字。
自定义函数和内置函数
| 函数 | 参数与返回值 | 细节 |
|---|---|---|
to_base(number, base) | 参数为非负整数和目标基数;返回目标进制字符串。 | 0 单独返回 "0";非零值循环除基数,余数用于索引 DIGITS 字符表。 |
int(text, base) | 内置函数;按 base 解释 text 并返回整数。 | base 为 2–36 或 0;本题白名单只允许 2、8、10、16。非法数字会 ValueError。 |
str.strip() | 无参数移除首尾空白,返回新字符串。 | 允许输入前后有空格;不会移除中间空白。 |
input().split() | 读取一行并按空白拆开,返回文本列表。 | 进制行需要恰好两个整数。 |
divmod(number, base) | 返回商与余数的二元组。 | 本题算法用它同时取得下一位和剩余商。 |
reversed(items) | 返回反向迭代器。 | 余数产生顺序与书写位序相反,必须反转。 |
str.join(iterable) | 将一串字符串片段用调用者字符串作为分隔符连接,返回 str。 | "".join(...) 表示无分隔连接。 |
手算 26 转十六进制
26 ÷ 16 = 1 余 10 → DIGITS[10] 是 A
1 ÷ 16 = 0 余 1 → DIGITS[1] 是 1
余数倒序读:1A当前函数设计给非负数和 2–16 范围内的 base 使用;主程序负责输入非负数和限定进制。本题十六进制字母表为大写 A–F。
代码如何运行
- 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
- 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
- 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。
先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。
自己动手试一试
试试 0、FF 转十进制、二进制转十六进制,以及输入不合法数字时的错误。
先在 lx22.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。