PYTHON LESSON 041
进制换算深潜营
掌握短除法与位权展开两套手工换算算法,理解负数补码的计算过程,做到“手工、函数双保险”。
00 · 学习目标
这一课要解决什么?
学完后,你应该能够
- 短除法:除基数取余,倒序排列
- 位权展开:每位数字 × 基数的位数次方再求和
- 补码 = 原码取反再加 1,& 0xFF 可看 8 位形态
01 · 核心概念
位权展开、短除法与补码再探
位权展开、短除法与补码再探:bin() 和 int() 固然方便,但考场上选择题常常不给电脑:给你 0b101101 问十进制是几,只能手算。手工算法还是理解进制的最好方式——会手算的人,用函数才不会用错。这节课我们给每个换算方向都配一套“手工算法”。
GESP Python 3 级 · 进制转换GESP Python 3 级 · 数据编码浮点数遵循 IEEE 754 的实现细节,不使用本章的普通整数进制模型直接推导。
02 · 语法与规则
先记住这 3 条,再开始写程序
短除法:除基数取余,倒序排列先准确读出这条写法的结构与作用。
位权展开:每位数字 × 基数的位数次方再求和换一组最小数据,手工推演一次结果。
补码 = 原码取反再加 1,& 0xFF 可看 8 位形态再用边界值或反例确认它的适用条件。
03 · 完整实例
代码、运行结果和解释放在一起看
# 进制换算深潜营:手工算法与补码
n = 45
# 短除法:十进制转二进制(除 2 取余,倒序排列)
t = n
s = ""
while t > 0:
s = str(t % 2) + s
t = t // 2
print(n, "手工转成二进制:", s)
print("bin() 验证:", bin(n))
# 位权展开:十六进制转十进制
h = "2f"
total = 0
power = 0
for ch in reversed(h):
if "0" <= ch <= "9":
v = int(ch)
else:
v = ord(ch) - ord("a") + 10
total = total + v * (16 ** power)
power = power + 1
print("十六进制", h, "手工转成十进制:", total)
print("int() 验证:", int(h, 16))
# 负数的补码:8 位二进制里 -45 长什么样
print("-45 的 8 位补码:", bin(-45 & 0b11111111))45 手工转成二进制: 101101 bin() 验证: 0b101101 十六进制 2f 手工转成十进制: 47 int() 验证: 47 -45 的 8 位补码: 0b11010011
手工换算与内置函数结果完全一致——两套方法互为验算,考场上才能双保险。
04 · 逐步理解
每一步只解决一个问题
- 01
为什么要学手工换算
bin() 和 int() 固然方便,但考场上选择题常常不给电脑:给你 0b101101 问十进制是几,只能手算。手工算法还是理解进制的最好方式——会手算的人,用函数才不会用错。这节课我们给每个换算方向都配一套“手工算法”。
- 02
短除法:十进制转二进制
把 45 不断除以 2,记下每次的余数:45 余 1、22 余 1、11 余 0、5 余 1、2 余 0、1 余 1。最后把余数从下往上倒序读:101101。代码里 while t > 0 循环做除法,s = str(t % 2) + s 把新余数拼到最前面,自然就完成了“倒序”。
while t > 0: s = str(t % 2) + s t = t // 2 - 03
位权展开:任意进制转十进制
十六进制 2f 从右往左的位权是 1、16:f 表示 15,所以 2×16 + 15×1 = 47。程序用 reversed(h) 从最右边开始扫,power 从 0 开始每次加 1,v * (16 ** power) 就是“数字 × 位权”。字母怎么变数字?ord(ch) - ord("a") + 10:f 是 a 之后第 5 个字母,5 + 10 = 15。
total = total + v * (16 ** power) - 04
字母数字的转换小技巧
判断字符是不是数字,用 "0" <= ch <= "9" 直接比较——字符比大小比的是编码值。数字字符用 int(ch) 转换,字母用 ord 换算。这两个小工具在进制题里出场率极高,一定要练熟。
if "0" <= ch <= "9": v = int(ch) - 05
补码再探:负数在计算机里的样子
正数 45 的 8 位原码是 00101101;取反得反码 11010010;再加 1 得补码 11010011——这就是 -45 在内存里的真实形态。Python 里 -45 & 0b11111111 正好能把低 8 位“切”出来看。口诀再背一遍:取反加一。
print(bin(-45 & 0b11111111)) - 06
双保险习惯
以后每道进制题都养成习惯:函数算一遍,手工验一遍(或者反过来)。考场上函数帮你抢时间,手工帮你抓错误——两套都熟,才叫真正掌握进制转换。
05 · 练习与检验
自己写出来,才算真正学会
- 1运行程序,对比手工结果与 bin()/int() 是否一致
- 2把 45 换成自己的幸运数字再跑一次
- 3手工把十进制 100 转成二进制,用程序验证
- 4试着解释为什么 -45 的 8 位补码是 11010011
06 · 完整知识
继续理解定义、规则和适用边界
第一次学习先完成上面的六个步骤;需要查定义、核对规则、分析误区或理解“为什么”时,再展开对应知识章。
计算机基础进制、整数表示与位运算从位权理解二、八、十六进制,准确使用补码模型、移位、掩码和 Python 大整数。+
正式定义
b 进制数按位权 b⁰、b¹…表示数值。进制只是同一个整数的书写方式;位运算直接处理整数的二进制位。Python 整数精度只受可用内存限制,负数位运算按无限长二进制补码语义定义。
必须掌握
- bin/oct/hex 生成带前缀字符串,int(text, base) 按指定进制解析;0b、0o、0x 是整数字面量前缀。
- 手工转十进制用位权展开,十进制转其他进制可连续除基取余并逆序。
- & 取共同为 1 的位,| 合并置位,^ 标记不同位,~x 等于 -x-1。
- x << k 相当于 x * 2**k;对非负整数 x >> k 相当于 x // 2**k。
- 掩码可检测、设置、清除或翻转特定位;位编号通常从最低位 0 开始。
- 固定字长语言的溢出和 Python 大整数行为不同,题目必须明确字长和有无符号。
常见误区
- 把进制字符串当成不同数值类型
- 忘记位编号从 0 开始
- 照搬固定 32 位溢出结论到 Python
- 对负数右移套用无符号模型
适用边界
- 浮点数遵循 IEEE 754 的实现细节,不使用本章的普通整数进制模型直接推导。
- 字符编码把字符映射到整数,但编码知识与整数进制书写是两个不同层次。
Python 基础条件、循环与程序流程准确理解 if、for、while、range、break、continue 和循环嵌套,而不是背代码模板。+
正式定义
控制流决定下一条要执行的语句。分支依据布尔条件选择路径;循环在满足规则时重复执行代码块。Python 用冒号和缩进界定代码块。
必须掌握
- if/elif/else 从上到下判断,只执行第一个为真的分支;else 不写条件。
- for 依次取得可迭代对象中的元素;range(start, stop, step) 包含 start、不包含 stop,step 不能为 0。
- while 在每轮开始前检查条件;循环体必须让状态向终止条件推进。
- break 结束最内层循环,continue 跳过本轮剩余语句,循环的 else 仅在没有被 break 终止时执行。
- 嵌套循环的总执行次数通常需要把各层次数相乘;内层 break 不会结束外层循环。
- 边界测试至少覆盖空范围、单个元素、第一项命中、最后一项命中和始终不命中。
常见误区
- range 的右端点多算或少算一次
- while 忘记更新状态造成死循环
- 把两个互斥条件写成两个独立 if
- 误以为 break 会跳出所有嵌套循环
适用边界
- 流程图是算法的表示方法,不是 Python 语法。
- 递归也能表达重复,但有调用开销和递归深度限制,不能无条件代替循环。
编码与文本ASCII、Unicode 与字符编码完整表完整查阅标准 ASCII 0–127,并理解 Unicode、编码方案与 Python 字符串之间的关系。+
正式定义
标准 ASCII 是 7 位字符编码,只定义十进制 0–127:0–31 与 127 是控制字符,32 是空格,33–126 是可打印字符。Unicode 为字符分配码点,UTF-8/UTF-16 是把码点编码成字节的方案;Unicode 的前 128 个码点与 ASCII 一致。
必须掌握
- 数字字符 '0'–'9' 是 48–57,大写字母 'A'–'Z' 是 65–90,小写字母 'a'–'z' 是 97–122。
- ord(ch) 返回单个 Unicode 字符的码点;chr(n) 返回对应码点的字符,它们不限于 ASCII。
- 字符串比较按 Unicode 码点逐项进行;大小写转换应优先使用 lower()/upper(),不要把“相差 32”推广到所有文字。
- str 是字符序列,bytes 是 0–255 的字节序列;encode() 从文字得到字节,decode() 从字节恢复文字。
- 所谓“扩展 ASCII”没有唯一标准,128–255 的含义取决于代码页,不能当成标准 ASCII 表的一部分。
- 换行符 LF 是 10,回车符 CR 是 13;Windows 文本常见 CRLF,跨平台读写要让文本模式正确处理。
常见误区
- 把 ASCII 说成所有字符的统一编号
- 认为 ord() 只能处理 ASCII
- 把字符个数等同于 UTF-8 字节数
- 把某个代码页的 128–255 当成统一的扩展 ASCII
适用边界
- 本页给出完整标准 ASCII 0–127;Unicode 有十多万个已分配字符,不适合平铺成一张儿童课程长表,应按码点和字符数据库检索。
- “扩展 ASCII”没有唯一标准,128–255 的解释必须同时注明代码页;字符显示还依赖字体,有合法码点也不等于当前字体一定有对应字形。
工程能力异常、文件、测试与调试读懂报错、缩小问题、设计测试,并安全地打开、读取和关闭文本文件。+
正式定义
异常是在运行期间表示错误或特殊情况的对象。调试是用可复现输入和证据定位实际行为与预期行为差异的过程;文件对象连接程序与持久化字节数据。
必须掌握
- 先读 traceback 最后一行的异常类型与消息,再从最靠近自己代码的栈帧向上追踪。
- try 只包可能失败的最小代码;except 捕获具体异常;else 处理成功路径;finally 做必需清理。
- raise 主动报告不满足的前置条件;assert 用于开发期内部假设,不用于校验不可信用户输入。
- with open(...) as file 会在退出代码块时可靠关闭文件。文本模式必须明确编码,本站统一推荐 encoding='utf-8'。
- 测试至少包含正常值、边界值、空数据、极端值和反例;每个测试只应有明确目的。
- 定位错误时一次只改一个假设,保留能稳定复现问题的最小输入。
常见误区
- 使用 except: 吞掉所有错误
- 只测题目样例就认为程序正确
- 文本文件不写 encoding
- 修复报错表象却不验证根因
适用边界
- 在线判题的学生代码由独立 Worker 执行;文件系统、网络和资源权限必须受平台限制。
- 二进制文件、JSON/CSV 和数据库各有专门格式与错误处理方式,不能按普通文本随意拆分。
完成检查