学计算机绕不开进制转换。这篇文章不背口诀,只讲人话:每个转换到底在干什么、为什么这么做、坑在哪里。看完记得动手算两遍,比看十遍都管用。
一、开头先说最重要的一句话
数没有变,只是写法变了。
十进制的 13,和二进制的 1101,和八进制的 15,和十六进制的 D,是同一个数。就像"十三"、"thirteen"、罗马数字"XIII"是同一个意思的不同写法。
所以进制转换不是"把一个数变成另一个数",而是换一套记号,把同一个数重新写一遍。想通这一点,后面所有方法你都不会觉得神秘。
二、认识一下这四种进制
末尾的字母是"身份牌":B = Binary,O = Octal,H = Hexadecimal,D = Decimal。没有后缀时默认十进制。
十六进制为什么冒出字母?因为它需要 16 个数字,09 只有 10 个不够用,只好借 AF 来代表 10、11、12、13、14、15。另外,十六进制数如果以字母开头(比如 D 开头),习惯在前面补个 0 写成 0DH,避免跟单词变量混淆。
为什么计算机偏偏偏爱二进制和十六进制?因为电路只认"高电平 / 低电平"两种状态,天然对应 0 和 1。而十六进制是二进制的缩写——后面你会看到,1 个十六进制数字正好顶 4 个二进制位。写代码时甩一长串 11010110 太累,用 D6 代替,又短又不容易抄错。
三、任何进制 → 十进制:按权展开(万能钥匙)
先学会这一招,它是所有转换里最基础的一个。
"权"就是每个位置的价值。十进制里 456 = 4×100 + 5×10 + 6×1,百位、十位、个位的权分别是 100、10、1——都是 10 的幂。
二进制同理,只是权换成了 2 的幂:
1101B = 1×8 + 1×4 + 0×2 + 1×1 = 13从右往左,权依次是 1、2、4、8、16、32、64、128……(也就是 2 的 0、1、2、3 次方……)
八进制、十六进制一模一样,只是权换成 8 或 16 的幂:
15O = 1×8 + 5×1 = 13
0DH = 13×1 = 13 (D 代表 13)
93H = 9×16 + 3×1 = 147
223O = 2×64 + 2×8 + 3×1 = 147小数部分也一样,只是权变成比 1 小的数:二进制小数点后各位的权依次是 0.5、0.25、0.125……
0.101B = 1×0.5 + 0×0.25 + 1×0.125 = 0.625先背下这张 2 的幂速查表,后面到处要用:
2⁰=1 2¹=2 2²=4 2³=8 2⁴=16 2⁵=32
2⁶=64 2⁷=128 2⁸=256 2⁹=512 2¹⁰=1024四、十进制 → 二进制
整数:除 2 取余,余数倒着读
做法:不断除以 2,记下每一步的余数,直到商为 0,然后从最后一步的余数往前读。
以 13 为例:
13 ÷ 2 = 6 …… 余 1 ↑
6 ÷ 2 = 3 …… 余 0 ↑
3 ÷ 2 = 1 …… 余 1 ↑
1 ÷ 2 = 0 …… 余 1 ↑ 从下往上读:1101所以 13 = 1101B。
为什么倒着读? 因为第一次除出来的余数是"个位"(最低位),最后除出来的才是最高位。写数时高位在前面,所以要把顺序倒过来。
为什么这样做是对的? 每次除以 2,余数恰好暴露出最低一位:13 是奇数,最低位必是 1;除完剩 6 是偶数,下一位是 0……相当于把"13 = 8 + 4 + 1"这件事一层层剥出来。
小数:乘 2 取整,正着读
做法:小数部分不断乘 2,每次"溢出"到整数部分的那个数字,就是下一个二进制位,按产生的顺序往下读。
以 0.625 为例:
0.625 × 2 = 1.25 → 取 1,剩 0.25
0.25 × 2 = 0.5 → 取 0,剩 0.5
0.5 × 2 = 1.0 → 取 1,剩 0,结束按顺序读:0.101B。
一个重要的坑:很多小数是乘不尽的!比如 0.1:
0.1 × 2 = 0.2
0.2 × 2 = 0.4
0.4 × 2 = 0.8
0.8 × 2 = 1.6 → 剩 0.6
0.6 × 2 = 1.2 → 剩 0.2 ← 开始循环了
……0.1 的二进制是 0.0001100110011…无限循环。这就是计算机里 0.1 + 0.2 ≠ 0.3 的根源——再大的内存也装不下无限位,只能截断,于是有了误差。
快捷法:凑 2 的幂(熟练后推荐)
把数拆成 2 的幂之和,哪位有就在哪位写 1。从高往低逐位判断,每步只做减法:
45 里有 32 → 剩 13 → 这位写 1
13 里有 16 吗?没有 → 写 0
13 里有 8 → 剩 5 → 写 1
5 里有 4 → 剩 1 → 写 1
1 里有 2 吗?没有 → 写 0
1 里有 1 → 剩 0 → 写 1结果:45 = 101101B。比老老实实做长除法快得多。
验算习惯(强烈推荐)
转完把二进制按权展开加回去:1101 = 8 + 4 + 0 + 1 = 13 ✓。三秒钟的事,转错了马上能发现。
五、二进制 ↔ 八进制:3 位一组
为什么是 3 位? 因为 2³ = 8:三个二进制位恰好能表示 0~7,正好对应一个八进制数字。所以八进制本质上就是二进制的缩写。
二进制 → 八进制:以小数点为界,整数部分向左每 3 位一组,小数部分向右每 3 位一组,每组换成一个八进制数字。
不够 3 位怎么办?补 0。整数部分在前面补,小数部分在后面补。原则是:补零不能改变数值的大小,所以只能往远离小数点的方向补。
例 1:11010110B
11 010 110
→ 补成 011 010 110
→ 011=3 010=2 110=6
→ 326O例 2(带小数):0.1011B
0.101 1
→ 补成 0.101 100
→ 101=5 100=4
→ 0.54O八进制 → 二进制:反过来,一位拆三位。每个八进制数字写成 3 位二进制,必须写满 3 位(包括开头的 0):
52O = 101 010 = 101010B
3O = 011 ← 别写成 11六、二进制 ↔ 十六进制:4 位一组
和八进制一模一样的把戏,只是 2⁴ = 16,改成每 4 位一组。
先背下这张对照表(这是全文唯一需要"死记"的部分,记熟后终身受用):
二进制 → 十六进制:4 位一组(补零规则同上:整数补头、小数补尾):
11010110B → 1101 0110 → D6H十六进制 → 二进制:一位拆四位:
93H = 1001 0011 = 10010011B
80H = 1000 0000 = 10000000B看到 80H,脑子里应该直接浮现 1000|0000 这两块——这就是"十六进制是二进制缩写"的含义,根本不用经过十进制中转。
七、八进制 ↔ 十六进制:二进制当桥
八进制和十六进制之间没有直达车,都要回二进制中转。道理很简单:机器内部只有二进制,八进制和十六进制都只是给人看的缩写,缩写之间互转自然要回到原文。
例:93H 转八进制。
第一步:每位十六进制数字展开成 4 位二进制:
93H = 1001 0011第二步:把 4 位分组的"格子线"擦掉,回到完整二进制串,从右往左重新按 3 位分组:
10010011
→ 10 010 011
→ 补成 010 010 011
→ 2 2 3
→ 223O验算:93H = 9×16 + 3 = 147;223O = 2×64 + 2×8 + 3 = 147 ✓
这里的坑:4 和 3 不是彼此的倍数,两套分组的格子线是错开的。必须先拆掉旧的分组、回到完整的二进制串,再重新分。不能把 1001、0011 两块各自直接转成八进制,那就错了。
八、十进制 ↔ 八进制 / 十六进制
两条路都通:
路线 A(直达):除 8 取余 / 除 16 取余,规则和除 2 取余完全一样(余数倒着读)。做十六进制时,余数 10
15 要写成 AF。路线 B(走桥):先转二进制,再 3 位 / 4 位分组。步骤多一点,但每一步都简单。
例:13 转十六进制。
路线 A:13 ÷ 16 = 0 余 13 → D,所以 0DH。
路线 B:13 = 1101B → 一组正好 4 位 → D → 0DH。
反方向(八进制 / 十六进制 → 十进制)就是第三节讲的按权展开,万能钥匙直接开。
九、最容易踩的坑汇总
余数倒着读:除基取余,第一个余数是最低位,要写在最右边。
补零方向:整数部分补在头(左边),小数部分补在尾(右边)。原则:补零不能改变数值,只能往远离小数点的方向补。
一位拆多位时必须写满:八进制一位拆三位、十六进制一位拆四位,开头的 0 不能省,3O 是 011 不是 11。
八和十六互转必须回二进制重新分组:4 位组和 3 位组的格子线是错开的,不能拿旧分组直接换算。
小数可能乘不尽(如 0.1),按题目要求的精度截断即可。
验算:按权展开加回去对一遍,永远是最稳的自检。
十、一分钟速查表
写在最后
进制转换的全部秘密就两句话:
数没变,只是写法变了——所以任何转换都能用"按权展开"验算。
二进制是计算机的母语,八进制和十六进制都只是它的缩写——所以它们之间互转要回二进制中转。
把这两句话想通了,剩下的都是熟练度问题。找几个数自己转一遍、验算一遍,比背十遍口诀都管用。
下一篇预告:位串本身没有含义——同一个 1000 0000,按无符号读是 128,按补码读是 -128。补码是什么?为什么计算机要用它?见后续文章。