数制,也称为进位计数制或基数系统(Radix System),是人类用来表示数量的符号体系。一个数制由两个核心要素决定:基数(Radix/Base)和位权(Positional Weight)。基数决定了该数制使用多少个不同的数字符号,而位权则决定了每个位置上的数字所代表的实际大小。
我们日常使用的十进制之所以使用10个符号(0-9),是因为人类有10根手指,这是最自然的计数方式。然而在计算机科学中,由于电子元件只有"通电"和"断电"两种状态,二进制(仅使用0和1两个符号)才是计算机的"母语"。八进制和十六进制则是二进制的便捷缩写形式,广泛用于编程和系统管理。
所有进位计数制都遵循相同的位值原理:一个数的值等于各个位上的数字乘以该位对应的权值之和。这就是"按权展开求和"法。
| 十进制 | 二进制 | 八进制 | 十六进制 |
|---|---|---|---|
| 0 | 0000 | 0 | 0 |
| 1 | 0001 | 1 | 1 |
| 2 | 0010 | 2 | 2 |
| 3 | 0011 | 3 | 3 |
| 4 | 0100 | 4 | 4 |
| 5 | 0101 | 5 | 5 |
| 6 | 0110 | 6 | 6 |
| 7 | 0111 | 7 | 7 |
| 8 | 1000 | 10 | 8 |
| 9 | 1001 | 11 | 9 |
| 10 | 1010 | 12 | A |
| 11 | 1011 | 13 | B |
| 12 | 1100 | 14 | C |
| 13 | 1101 | 15 | D |
| 14 | 1110 | 16 | E |
| 15 | 1111 | 17 | F |
将十进制整数转换为N进制,最经典的方法是"短除法"(也叫"除N取余法"):不断将数除以目标基数N,记录每次的余数,直到商为0,然后将余数从下往上排列即为结果。
计算机使用二进制并非偶然的设计选择,而是由硬件物理特性决定的。电子电路中,晶体管只有两种稳定状态——导通(高电平,代表1)和截止(低电平,代表0)。使用二进制可以最大限度地提高信号的抗干扰能力:即使电压出现一定波动,也能清晰地区分0和1两种状态。如果使用十进制,就需要精确区分10个不同的电压等级,这在工程上极其困难且容易出错。
此外,布尔代数(Boolean Algebra)天然适用于二进制运算,所有逻辑运算(AND、OR、NOT、XOR)都可以用简单的电路门实现,这使得CPU的算术逻辑单元(ALU)设计变得高效而可靠。
十六进制是程序员最常用的进制之一,因为它与二进制有天然的简洁对应关系:每1个十六进制数字恰好对应4个二进制位(bit),每2个十六进制数字恰好表示1个字节(byte)。
| 应用领域 | 十六进制示例 | 含义说明 |
|---|---|---|
| CSS/HTML颜色 | #FF0000 | 红色,R=255, G=0, B=0 |
| CSS/HTML颜色 | #336699 | R=51, G=102, B=153,一种蓝灰色 |
| 内存地址 | 0x7FFF5FBFF8AC | 64位系统中的栈地址 |
| MAC地址 | AA:BB:CC:DD:EE:FF | 网卡硬件地址,6个字节 |
| Unicode字符 | U+4E2D | "中"字的Unicode码点 |
| IPv6地址 | 2001:0db8::0001 | 128位IP地址的十六进制表示 |
| 字节序列 | 0xDEADBEEF | 程序员常用的调试标记值 |
八进制在现代编程中最常见的用途是表示Unix/Linux文件权限。每个文件有三组权限(所有者、所属组、其他用户),每组权限由读(r=4)、写(w=2)、执行(x=1)三个位组成。由于每组权限恰好用3个二进制位表示,而1个八进制数字也是3位,因此八进制是表示文件权限的最自然方式。
| 八进制数字 | 二进制 | 权限含义 | 符号表示 |
|---|---|---|---|
| 0 | 000 | 无权限 | --- |
| 1 | 001 | 仅执行 | --x |
| 2 | 010 | 仅写入 | -w- |
| 4 | 100 | 仅读取 | r-- |
| 5 | 101 | 读取+执行 | r-x |
| 6 | 110 | 读取+写入 | rw- |
| 7 | 111 | 读+写+执行 | rwx |
例如 chmod 755 表示:所有者拥有全部权限(7=rwx)、所属组拥有读和执行权限(5=r-x)、其他用户拥有读和执行权限(5=r-x)。
| 进制 | 前缀写法 | 代码示例 | 支持的语言 |
|---|---|---|---|
| 二进制 | 0b 或 0B | 0b11111111 = 255 | C/C++、Java、Python、JavaScript |
| 八进制 | 0o 或 0O(旧式:0) | 0o377 = 255 | Python 3、JavaScript(ES6)、Go |
| 十六进制 | 0x 或 0X | 0xFF = 255 | 几乎所有编程语言 |