要学习的知识点
- ASCII 与字符编码
- ord()
- 二进制位运算
- 格雷码编码
- 逐位异或解码
题目
练习 18:输出字符的 ASCII 码,并进行整数与格雷码的相互转换。
输入:第一行一个 ASCII 字符,第二行一个非负整数。
完整代码
以下内容与 ex18.py 一致,可对照右侧讲解阅读。
"""练习 18:输出字符的 ASCII 码,并进行整数与格雷码的相互转换。
输入:第一行一个 ASCII 字符,第二行一个非负整数。
学习说明:
- ord(character) 返回字符的编码数值;ASCII 字符只占用 ASCII 字符集范围。
- 格雷码的转换公式是 n ^ (n >> 1),^ 表示按位异或,>> 表示向右移位。
- 解码时,binary_value 保存当前还原结果;把格雷码不断右移,并与结果异或。
- 最终的 binary_value 应与输入整数相同,可用来检查转换过程。
"""
character = input()
number = int(input())
if len(character) != 1 or not character.isascii():
raise ValueError("第一行必须输入一个 ASCII 字符")
if number < 0:
raise ValueError("第二行必须输入非负整数")
ascii_code = ord(character)
gray_code = number ^ (number >> 1)
# 格雷码解码:格雷码与它逐次右移后的值进行异或,得到原二进制数。
binary_value = gray_code
shifted = gray_code >> 1
while shifted:
binary_value ^= shifted
shifted >>= 1
print("ASCII:", ascii_code)
print("gray:", gray_code)
print("decoded:", binary_value)
进阶写法
这版与初学版解决同一道题,使用更精炼的语法或标准库工具。
进阶源码:ex18_adv.py
"""练习 18 进阶版:用 ord 转码,并用逐次右移的前缀异或解码格雷码。"""
character = input()
number = int(input())
if len(character) != 1 or not character.isascii():
raise ValueError("第一行必须输入一个 ASCII 字符")
if number < 0:
raise ValueError("第二行必须输入非负整数")
gray_code = number ^ (number >> 1)
binary_value = 0
remaining_bits = gray_code
while remaining_bits:
binary_value ^= remaining_bits
remaining_bits >>= 1
print("ASCII:", ord(character))
print("gray:", gray_code)
print("decoded:", binary_value)
解码时将格雷码不断右移,并将每个前缀与结果异或;循环直到移位值为 0。
运行结果
示例输入:
A
13程序输出:
ASCII: 65
gray: 11
decoded: 13逐个认识函数
下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。
| 函数形式 | 功能与返回值 | 注意事项 |
|---|---|---|
ValueError(message) | 内置异常类型,用来表示参数值不符合要求。 | raise ValueError(...) 会立即抛错并停止当前程序流程。 |
str.isascii() | 判断字符串是否全部由 ASCII 字符组成,返回 bool。 | 空字符串也会返回 True。 |
input(prompt='') | 读取一行文本,返回 str;若提供 prompt 会先显示提示。 | 返回值默认是字符串,计算前通常要做类型转换。 |
int(value, base=10) | 把整数文本或数值转换为整数。 | int('3.5') 不合法;按指定进制解析时可传 base。 |
len(container) | 返回字符串、列表、元组等对象的元素个数。 | 整数等没有长度的对象不能传入。 |
ord(character) | 返回单个字符对应的 Unicode 编码整数。 | 只有限制在 ASCII 范围时才等同 ASCII 码。 |
print(*objects, sep=' ', end='\n') | 把对象转换为文本显示;返回 None。 | 默认空格分隔并在末尾换行。 |
ASCII 与字符函数
| 函数 / 方法 | 参数和返回值 | 用法与注意 |
|---|---|---|
input() | 无必需参数,返回输入的一行字符串。 | 第一行字符,第二行整数。 |
len(text) | 返回字符串字符数。 | 检查字符长度是否为 1。Python 的字符串长度按 Unicode 码点计数。 |
text.isascii() | 无参数;字符串字符全在 ASCII 范围时返回 True。 | 限制本题为 ASCII;空字符串对该方法返回 True,但 len 检查会挡住它。 |
ord(character) | 接受一个长度为 1 的字符串,返回其 Unicode 编码整数。 | 本题限制 ASCII,所以结果正是 ASCII 码;一般 Unicode 字符的 ord 值不一定属于 ASCII。 |
int(text) | 将整数文本转换为 int。 | 输入非负值,程序检查 number<0。 |
格雷码是什么
普通二进制相邻数可能多位变化,比如 3=011、4=100,三位都变。格雷码排序相邻项只改变一位,常用于位置编码和减少转换瞬间的读数错误。
编码公式:gray = n ^ (n >> 1)。>> 1 是二进制右移一位,^ 是按位异或:相同位得 0,不同位得 1。
| 函数/运算 | 说明 |
|---|---|
^ | 按位异或运算符,不是函数。 |
>> | 右移运算符;正整数右移一位相当于整除 2。 |
^= | 异或后赋值,等价于 a = a ^ b。 |
解码:逐个恢复二进制位
格雷码最高位与原二进制最高位相同。之后每一位原值等于“上一位原值 XOR 当前格雷位”。程序用前缀异或来实现:先令结果等于整个格雷数,然后将格雷码右移 1、2、3...位,依次与结果异或,直到 shifted 为 0。
binary_value = gray_code
shifted = gray_code >> 1
while shifted:
binary_value ^= shifted
shifted >>= 1程序最后打印 decoded。应与原输入 number 完全相同;这是验证编码与解码互逆的办法。
代码如何运行
- 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
- 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
- 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。
先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。
自己动手试一试
测试整数 0、1、2、13 和一个更大的数;每次确认解码结果等于原数。
先在 lx18.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。