进制转换指南:二进制、十六进制、八进制详解
如果你曾盯着 #1A2B3C 这样的十六进制颜色代码,或是 chmod 755 这样的 Unix 权限设置,好奇这些数字究竟从何而来,你并不孤单。进制是大多数开发者每天都在使用却很少深想的基础概念——直到真正需要在不同进制之间进行转换的那一刻。
让我们来彻底搞清楚它。本指南将带你了解编程中常见的数制系统、如何在它们之间进行转换,以及每种进制在实际中的应用场景。
"进制"到底是什么意思?
我们日常使用十进制(base-10)来计数,因为我们有十根手指。每个数位代表 10 的一个幂次:
4 2 7
| | |
| | └── 7 × 10⁰ = 7
| └────── 2 × 10¹ = 20
└────────── 4 × 10² = 400
───
Total = 427
这就是位值记数法。"进制"(也叫基数)决定了该数制中有多少个不同的数字符号,以及每个位置的乘数是多少。十进制有 0–9 共十个数字,二进制有 0–1 两个数字,十六进制有 0–9 加上 A–F 共十六个符号。
这个概念在所有进制中完全相同——唯一的区别在于可用符号的数量和每个位置的乘数。
趣闻:古巴比伦人使用六十进制(sexagesimal)。这就是为什么一分钟有 60 秒、一个圆有 360 度。
二进制(Base-2):硬件的语言
计算机为什么使用二进制
计算机依靠晶体管运行,而晶体管有两种可靠的状态:开和关。这恰好对应 1 和 0。理论上你可以制造一台三进制计算机,但区分三种电压水平比区分两种更困难、更容易出错。二进制之所以胜出,是因为它简单且可靠。
读懂二进制数
二进制的工作原理与十进制相同,只不过每个位置代表 2 的幂次:
1 0 1 1 0 1
| | | | | |
| | | | | └── 1 × 2⁰ = 1
| | | | └────── 0 × 2¹ = 0
| | | └────────── 1 × 2² = 4
| | └────────────── 1 × 2³ = 8
| └────────────────── 0 × 2⁴ = 0
└────────────────────── 1 × 2⁵ = 32
──
Total = 45
所以二进制的 101101 等于十进制的 45。从右到左读取,每个位置的权值翻倍:1、2、4、8、16、32、64、128……
位、半字节与字节
- 位(Bit):一个二进制数字(0 或 1)
- 半字节(Nibble):4 位(对应一个十六进制数字,取值 0–15)
- 字节(Byte):8 位(取值 0–255)
- 千字节(Kilobyte):1,024 字节(2¹⁰)
一个字节可以表示 256 个不同的值,这就是为什么 ASCII 字符可以用一个字节存储,RGB 颜色通道的范围是 0 到 255。
二进制算术基础
二进制加法与十进制遵循相同规则,只不过逢 2 进位而不是逢 10:
1 0 1 1 (11 in decimal)
+ 0 1 1 0 ( 6 in decimal)
─────────
1 0 0 0 1 (17 in decimal)
当二进制中 1 + 1 = 10 时(就像十进制中 9 + 1 = 10),写 0 并进 1。
八进制(Base-8):历史遗留的进制
简史
八进制在 20 世纪 60 至 70 年代非常流行,尤其是在 PDP-8 等使用 12 位字长的机器上——12 位恰好可以整除为四组三位。每个八进制数字精确对应三个二进制数字,因此它是一种方便的简写方式。
八进制的现代应用
如今最常见的应用场景是 Unix 文件权限。当你输入 chmod 755 script.sh 时,每个数字都是一个八进制数,分别代表读取(4)、写入(2)和执行(1)权限:
7 = 4 + 2 + 1 = rwx (owner: read, write, execute)
5 = 4 + 0 + 1 = r-x (group: read, execute)
5 = 4 + 0 + 1 = r-x (others: read, execute)
编程语言中的八进制使用 0o 前缀(C 语言中则使用前导 0,这导致了不少 bug):
const permissions = 0o755; // 493 in decimal
console.log(permissions.toString(8)); // "755"
在 JavaScript 和 Python 中要注意:像 0755 这样的前导零在某些上下文中可能被解释为八进制。请始终使用明确的 0o 前缀以避免歧义。
十六进制(Base-16):开发者的最爱
十六进制为何存在
十六进制解决了一个实际问题:二进制数太长了。十进制的 255 用二进制表示是 11111111——整整八位。而用十六进制表示只需 FF。每个十六进制数字精确对应四个二进制数字(即一个半字节),这使得转换轻而易举,同时保持数字紧凑。
十六进制使用 0–9 加上字母 A–F:
| Decimal | Binary | Hex |
|---|---|---|
| 0 | 0000 | 0 |
| 1 | 0001 | 1 |
| 9 | 1001 | 9 |
| 10 | 1010 | A |
| 11 | 1011 | B |
| 15 | 1111 | F |
十六进制的实际应用
网页颜色是十六进制最直观的用途。#FF5733 的解析如下:
#FF5733
││││││
││││└┘── Blue: 0x33 = 51
││└┘──── Green: 0x57 = 87
└┘────── Red: 0xFF = 255
调试器中的内存地址以十六进制显示:0x7FFF5FBFFA10 比其十进制等值 140,734,799,804,944 更易读。
MAC 地址使用冒号分隔的十六进制对:A4:83:E7:2B:00:1F。
CSS 颜色:rgba(255, 87, 51, 1.0) 和 #FF5733 表示同一种颜色——十六进制写法更简洁。
不同进制之间的转换
十进制转二进制
反复除以 2 并收集余数,从下往上读取:
45 ÷ 2 = 22 remainder 1 ↑
22 ÷ 2 = 11 remainder 0 │
11 ÷ 2 = 5 remainder 1 │ Read upward:
5 ÷ 2 = 2 remainder 1 │ 101101
2 ÷ 2 = 1 remainder 0 │
1 ÷ 2 = 0 remainder 1 │
结果:十进制 45 = 二进制 101101。
十进制转十六进制
方法相同,但除以 16:
427 ÷ 16 = 26 remainder 11 (B) ↑
26 ÷ 16 = 1 remainder 10 (A) │ Read upward: 1AB
1 ÷ 16 = 0 remainder 1 │
结果:十进制 427 = 十六进制 1AB。
二进制转十六进制(最简单的转换)
将二进制数字从右到左每四位一组,分别转换:
Binary: 10 1101
Padded: 0010 1101
Groups: 2 D
Result: 0x2D
验证:0x2D = 2×16 + 13 = 45 ✓
这就是为什么十六进制和二进制是天然搭档——转换完全是机械化的。
十六进制转二进制
反过来操作。将每个十六进制数字展开为四位二进制:
Hex: F A 3
Binary: 1111 1010 0011
Result: 111110100011
提示:记住 0–F 对应的二进制模式(总共只有 16 个)。一旦掌握,十六进制与二进制之间的转换就能在脑中瞬间完成。从 2 的幂次开始记:1=0001、2=0010、4=0100、8=1000。
编程语言中的进制表示法
每种主流编程语言都支持以不同进制书写数字的语法:
// JavaScript
const binary = 0b101101; // 45
const octal = 0o55; // 45
const hex = 0x2D; // 45
const decimal = 45; // 45
// Convert to string in any base
(45).toString(2); // "101101"
(45).toString(8); // "55"
(45).toString(16); // "2d"
// Parse from string
parseInt("101101", 2); // 45
parseInt("55", 8); // 45
parseInt("2D", 16); // 45
# Python
binary = 0b101101 # 45
octal = 0o55 # 45
hexval = 0x2D # 45
# Convert to string
bin(45) # '0b101101'
oct(45) # '0o55'
hex(45) # '0x2d'
# Parse from string
int("101101", 2) # 45
int("55", 8) # 45
int("2D", 16) # 45
// C / C++
int binary = 0b101101; // 45 (C23 / GCC extension)
int octal = 055; // 45 (leading zero = octal!)
int hex = 0x2D; // 45
注意 C 语言的坑:前导 0 表示八进制。写 int x = 010; 得到的是 8,而不是 10。这已经坑过无数程序员了。
实际应用场景
位运算和标志位
十六进制是位掩码的标准写法,因为每个数字恰好覆盖四个标志位:
const READ = 0x01; // 0001
const WRITE = 0x02; // 0010
const EXECUTE = 0x04; // 0100
const ADMIN = 0x08; // 1000
let permissions = READ | WRITE; // 0x03 = 0011
if (permissions & EXECUTE) {
// check if execute bit is set
}
调试与内存检查
当你在地址 0xDEADBEEF 遇到段错误,或用 0xCAFEBABE 初始化内存时,这些都是专门选定的十六进制常量,因为它们在内存转储中非常容易辨识。Java 类文件以魔术数字 0xCAFEBABE 开头——没错,命名的人确实很有幽默感。
网络协议
IPv6 地址使用十六进制表示法:2001:0db8:85a3:0000:0000:8a2e:0370:7334。MAC 地址、USB 厂商 ID 和蓝牙 UUID 都使用十六进制表示,因为它使二进制数据保持紧凑且可读。
动手试试
不必手动计算。我们的进制转换器可以即时完成任意进制之间的转换——十进制、二进制、八进制、十六进制,或任何最高到 36 进制的自定义进制。粘贴一个数字,选择源进制和目标进制,即刻获得结果。一切运算都在你的浏览器中完成,不会向服务器发送任何数据。
它在以下场景中尤其有用:
- 调试十六进制内存转储时转换为十进制
- 用二进制/八进制计算 Unix 权限
- 在十六进制和 RGB 值之间验证颜色代码
- 在非 2 的幂次的进制之间进行转换
相关资源
- Base64 编码详解 — Base64 使用不同的方法(6 位一组映射到 64 个字符)将二进制编码为文本
- 哈希算法对比 — 哈希输出通常以十六进制显示
- 进制转换器 — 在浏览器中即时转换任意进制
🛠️ 立即试用: 进制转换器 — 在二进制、八进制、十进制、十六进制以及最高 36 进制之间自由转换。100% 客户端运算,完全免费。