二进制、八进制、十六进制指的是同一批数,只是写法不同。 电脑只认二进制,因为一根线只有两种状态——有电、没电。 十六进制是二进制的压缩写法:每四位二进制正好对应一位十六进制。
前七章讲「怎么想」,这一章往下钻一层:电脑用什么表示数。 这是全书唯一一章不涉及算法、只涉及表示的章节,但它是前面所有算法的地基。 这一篇先把三种进制的写法认清楚,下一篇讲怎么互转。
一、同一个数,四种写法
十进制 173、二进制 0b10101101、八进制 0o255、十六进制 0xad——这四个指的是同一个数。
就像「173」「一百七十三」「CLXXIII」是同一个数一样:写法不同,数没变。
进制只是「逢几进一」的规矩。十进制逢十进一,二进制逢二进一,十六进制逢十六进一。
| 进制 | 写法 | 用了几种数字 | 位数 |
|---|---|---|---|
| 十进制 | 173 | 0~9 共 10 种 | 3 |
| 二进制 | 0b10101101 |
0 和 1 两种 | 8 |
| 八进制 | 0o255 |
0~7 共 8 种 | 3 |
| 十六进制 | 0xad |
0~9 加 A~F 共 16 种 | 3 |
注意位数那一列:同一个数,二进制要 8 位,其他三种都是 3 位。这就是二进制「不好读」的具体表现。
Python 里那三个前缀(0b、0o、0x)就是用来区分写法的——不加前缀,
10101101 会被当成十进制的一亿多。
二、为什么电脑只认二进制
演示里那句话最直白:一根线只有两种状态——有电、没电。 两个状态正好对上 0 和 1。 要是想用十进制,一根线得能分出十档电压,档位一多,干扰一起来就分不清了。 这跟机械时代的算盘不一样:算盘的珠子位置是「看得见摸得着」的,分十档没问题。 电子元件靠电压判断,电压本身是有噪声的——档位越少越可靠。
所以硬件层面只有 0 和 1。八进制、十六进制都是给人看的,电脑内部还是那一串 0 和 1。 这条区分很重要:进制不是电脑的需要,是人的需要。人受不了看八个 0 和 1, 才发明了十六进制这种缩写。
三、十六进制为什么好读
173 的二进制是 10101101,八位,一眼数不清。
把它四位一组切开:1010 和 1101。1010 是十进制 10,写作 A;1101 是 13,写作 D。
合起来就是 AD。
两位数就写完了。这就是十六进制在编程里到处都是的原因——它是二进制的压缩写法。
| 二进制四位 | 十进制 | 十六进制 |
|---|---|---|
| 0000 | 0 | 0 |
| 1001 | 9 | 9 |
| 1010 | 10 | A |
| 1101 | 13 | D |
| 1111 | 15 | F |
为什么正好是四位对一位?因为 2 的 4 次方是 16。这也是十六进制存在的原因——16 是 2 的整数次幂。 所以转换时不用算,照着表抄就行。这一条让十六进制成了「人机之间最省事的桥」。
四、最常见的一处:颜色
#A3F2C1 这样的颜色值,拆开是三组两位十六进制:A3、F2、C1。
分别是红 163、绿 242、蓝 193。每组两位十六进制,范围正好 0 到 255,也就是 8 位二进制。
三个 255 是纯白 #FFFFFF,三个 0 是纯黑 #000000。
这一条能解释很多日常现象:为什么颜色值总是 6 位(三组各两位),
为什么「16 位色」「24 位色」这么叫(每个像素占多少位)。
所以看到 # 开头的六位色值,就可以理解了:它不过是「三个 8 位二进制数」的缩写,
而每一位都能在 0 到 255 之间取值,因为 8 位二进制最大就是 255。
五、动手 Demo:一个数,四种写法,顺便拆一个颜色值
用 Python 的三种前缀把 173 分别写成二进制、八进制、十六进制。 再把一个颜色值拆成三组,看每组的十进制是多少。
n = 173
print(n)
print(bin(n))
print(oct(n))
print(hex(n))
print(bin(n)[2:])
print(0b10101101, 0o255, 0xad)
c = 'A3F2C1'
print([int(c[i:i + 2], 16) for i in range(0, 6, 2)])
print(int('FF', 16), int('FF', 16) * 3)
实跑输出:
--------------------------------------------------------------------
二进制、八进制与十六进制
--------------------------------------------------------------------
① 同一个数,四种写法
--------------------------------------------------------------------
| 进制 | 写法 | 用了几种数字 | 位数 |
|---|---|---|---:|
| 十进制 | 173 | 0~9 共 10 种 | 3 |
| 二进制 | 0b10101101 | 0 和 1 两种 | 8 |
| 八进制 | 0o255 | 0~7 共 8 种 | 3 |
| 十六进制 | 0xad | 0~9 加 A~F 共 16 种 | 3 |
这四个指的是同一个数。就像「173」「一百七十三」「CLXXIII」是同一个数一样——写法不同,数没变。
② 为什么电脑只认二进制
--------------------------------------------------------------------
一根线只有两种状态:有电、没电。
两个状态正好对上 0 和 1,多一个状态就得靠「电压分几档」
来分辨——档位一多,干扰一起就分不清了。
所以硬件层面只有 0 和 1。八进制、十六进制是给人看的,电脑内部还是那一串 0 和 1。
③ 十六进制为什么好读
--------------------------------------------------------------------
十进制 173 的二进制是 10101101,八位,一眼数不清。
把它四位一组切开:1010 1101
1010 是十进制的 10,写作 A;1101 是 13,写作 D
合起来就是 AD ——两位就写完了。
| 二进制四位 | 十进制 | 十六进制 |
|---|---|---|
| 0000 | 0 | 0 |
| 1001 | 9 | 9 |
| 1010 | 10 | A |
| 1101 | 13 | D |
| 1111 | 15 | F |
每四位二进制正好对应一位十六进制,所以转换时不用算,直接照着表抄。
这就是十六进制在编程里到处都是的原因——它是二进制的「压缩写法」。
④ 最常见的一处:颜色
--------------------------------------------------------------------
#A3F2C1 这样的颜色值,拆开是三组两位十六进制:
A3 F2 C1 -> 红 163,绿 242,蓝 193
每组两位十六进制,范围正好是 0 到 255,也就是 8 位二进制。
三个 255 是纯白 #FFFFFF,三个 0 是纯黑 #000000。
这一条能解释很多日常现象:为什么颜色值总是 6 位、
为什么「16 位色」叫这个名字——都是二进制位数换了个说法。
①bin、oct、hex 都带前缀(0b、0o、0x)。要纯数字就用 [2:] 切掉前面两个字符。
②第三段反过来:把三种写法的字面量直接打印,出来都是 173。同一个数,四种写法,值一样。
③int(c[i:i+2], 16) 是「按十六进制解析这两个字符」。第二个参数就是进制,换成 2 就是按二进制解析。
④最后一行两个数:255 和 765。255 是 8 位二进制能表示的最大值,所以每个颜色通道最多就到这儿。
30 秒实验
- 把 255 写成二进制,看是不是正好八个 1。
- 把
#000000和#FFFFFF各拆一遍,验证是 0 和 255。 - 试一下
int('1010', 2)和int('1010', 16),看两个结果差多少。
常见误区
- 「二进制、八进制、十六进制是三种不同的数。」是同一个数的三种写法。
- 「电脑里存的是十六进制。」存的还是 0 和 1,十六进制只是给人看的缩写。
- 「颜色值 6 位是随便定的。」三组各两位,每组 8 位二进制,所以是 6 位。
自测三问(点开对答案)
1. 为什么电脑内部只用二进制? —— 一根线只有通电和不通电两种状态。档位越多越容易被干扰分不清。 2. 十六进制为什么好读? —— 每四位二进制正好对应一位十六进制,转换时照表抄,不用算。 3. 颜色值里每个通道为什么最大是 255? —— 每个通道占 8 位二进制,8 位全 1 就是 255。写法认清了,接下来要会换。下一节讲两件手工活:除二取余 和 按位权展开。
- ☐ (本篇完,下一篇 8.2 二进制与十进制互转)