要学习的知识点
- 固定 8 位表示
- 原码、反码、补码
- 位移、按位与和按位或
- format() 二进制格式
- 符号位与边界范围
题目
补充练习:将 -127 到 127 的整数编码为 8 位原码、反码和补码。
输入一个整数。补充覆盖考试大纲中的数据编码内容。
完整代码
以下内容与 ex19.py 一致,可对照右侧讲解阅读。
"""补充练习:将 -127 到 127 的整数编码为 8 位原码、反码和补码。
输入一个整数。补充覆盖考试大纲中的数据编码内容。
学习说明:
- 8 位编码中最高位作为符号位;本练习范围排除了 -128,避免补码范围与原码范围不同的问题。
- 非负数的三种表示相同,直接使用数值即可。
- 负数原码:最高位置 1,其余位保存绝对值。
- 负数反码:对绝对值按位取反,并用 & 0xFF 限制为 8 位。
- 负数补码:相当于 256 加上负数;& 0xFF 取出最低 8 位。
- format(value, "08b") 把数字显示成至少 8 位的二进制字符串。
"""
number = int(input())
if not -127 <= number <= 127:
raise ValueError("本练习范围为 -127 到 127")
if number >= 0:
# 正数的符号位为 0,三种编码相同。
sign_magnitude = number
ones_complement = number
twos_complement = number
else:
# 负数的三种编码按不同规则生成。
magnitude = -number
sign_magnitude = (1 << 7) | magnitude
ones_complement = (~magnitude) & 0xFF
twos_complement = (-magnitude) & 0xFF
print("sign-magnitude:", format(sign_magnitude, "08b"))
print("ones-complement:", format(ones_complement, "08b"))
print("twos-complement:", format(twos_complement, "08b"))
进阶写法
这版与初学版解决同一道题,使用更精炼的语法或标准库工具。
进阶源码:ex19_adv.py
"""练习 19 进阶版:用位掩码生成 8 位原码、反码和补码。"""
number = int(input())
if not -127 <= number <= 127:
raise ValueError("本练习范围为 -127 到 127")
magnitude = abs(number)
is_negative = number < 0
sign_magnitude = (int(is_negative) << 7) | magnitude
ones_complement = ((~magnitude) & 0xFF) if is_negative else number
twos_complement = number & 0xFF
print("sign-magnitude:", format(sign_magnitude, "08b"))
print("ones-complement:", format(ones_complement, "08b"))
print("twos-complement:", format(twos_complement, "08b"))
int(is_negative) 把布尔值转成 0 或 1;左移 7 位构造符号位,按位掩码 & 0xFF 保留 8 位。条件表达式选择正数或负数编码规则。
运行结果
示例输入:
-5程序输出:
sign-magnitude: 10000101
ones-complement: 11111010
twos-complement: 11111011逐个认识函数
下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。
| 函数形式 | 功能与返回值 | 注意事项 |
|---|---|---|
ValueError(message) | 内置异常类型,用来表示参数值不符合要求。 | raise ValueError(...) 会立即抛错并停止当前程序流程。 |
format(value, format_spec='') | 返回按格式规范转换后的字符串。 | 格式代码 b 表示二进制,宽度可用于补前导零。 |
input(prompt='') | 读取一行文本,返回 str;若提供 prompt 会先显示提示。 | 返回值默认是字符串,计算前通常要做类型转换。 |
int(value, base=10) | 把整数文本或数值转换为整数。 | int('3.5') 不合法;按指定进制解析时可传 base。 |
print(*objects, sep=' ', end='\n') | 把对象转换为文本显示;返回 None。 | 默认空格分隔并在末尾换行。 |
三种表示法
| 表示 | 正数 | 负数 |
|---|---|---|
| 原码 | 最高位 0 表示正,其他位表示大小。 | 最高位 1 表示负,其他位仍写绝对值。 |
| 反码 | 与原码相同。 | 符号位保留为 1,其余数值位取反;本例等价于对 8 位正数取反。 |
| 补码 | 与原码相同。 | 正数对应二进制按位取反再加 1;也等价于把负数加 256 后取最低 8 位。 |
本练习选择 -127 到 127,避开 8 位补码可表示 -128、但原码不能表示其正负对称值的特殊边界。
本题位运算和格式化函数
| 写法 | 功能与返回值 | 例子 / 注意点 |
|---|---|---|
1 << 7 | 整数左移 7 位,结果是二进制的第 8 位权值 128。 | 用于把原码符号位设为 1。 |
| | 按位或运算符;任一位为 1,结果该位就是 1。 | 128 | 5 把符号位和绝对值位组合起来。 |
~value | 按位取反运算符,不是函数。 | Python 整数按任意精度表示,负数取反需用掩码限制成 8 位。 |
& 0xFF | 按位与掩码;只保留最低 8 位。 | 0xFF 是十六进制的 255,即二进制 11111111。 |
format(value, "08b") | 内置格式化函数;返回格式化字符串。 | b 表示二进制,08 表示宽度 8、不够时左侧补 0。 |
int(input()) | 读入并转换整数。 | 越界时程序主动抛出 ValueError。 |
负数 -5 的计算
- 原码:符号位 1,绝对值 5 写成 7 位 0000101,合成 10000101。
- 反码:对 00000101 的 8 位表示 00000101 取反,得到 11111010。
- 补码:在 -5 的二进制结果中只保留低 8 位,得到 11111011;也可由反码加 1。
magnitude = -number # 5
sign_magnitude = 128 | 5 # 133 -> 10000101
ones_complement = (~5) & 255
twos_complement = (-5) & 255代码使用 format(..., "08b") 显示位串。提示:原码计算这条示例中的“7 位绝对值”只是说明符号位外的 7 位区域,格式结果统一显示 8 位。
二进制负数的纸笔推导要严格区分“对 8 位正数整体取反”和“符号位保持不变、只反转数值位”的表述。本程序的反码实现是 (~magnitude) & 0xFF。
代码如何运行
- 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
- 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
- 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。
先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。
自己动手试一试
测试 0、正负 1、正负 127;对照纸笔推导的三种 8 位二进制表示。
先在 lx19.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。