二进制转八进制:完整指南(含对照表、示例与代码)
学习如何使用 3 位分组法将二进制转换为八进制。包含完整的转换对照表(0-255)、分步示例、Python/JavaScript/C 代码,以及 Unix 文件权限中的实际应用。
二进制转八进制:完整指南(含对照表、示例与代码)
二进制转八进制是数制运算中最简洁的操作之一。由于八进制是以 8 为基数,而 8 恰好是 2 的精确幂次(2³ = 8),每一个八进制数字都精确对应三个二进制位。无需舍入、无需余数、无需繁琐的长除法——只是直接的机械替换。这种对应关系使八进制曾是早期计算机的常用记数法,时至今日,它对于处理 Unix/Linux 文件权限、遗留代码库或嵌入式系统的人来说仍不可或缺。
本指南涵盖二进制转八进制的完整理论与实践。你将学到:转换原理、手工转换方法、处理奇数位二进制字符串等边界情况,以及如何编写代码来完成转换。欢迎使用我们的免费二进制转八进制工具,边阅读边对下面的示例进行实操验证。
数制概述
在深入转换之前,先了解程序员最常接触的四种数制会大有裨益。
二进制(基数 2)
二进制只使用两个符号:0 和 1。每台数字计算机都建立在二进制逻辑之上,因为晶体管有两种工作状态——开和关。虽然二进制是硬件的原生语言,但对人类来说相当冗长:十进制数 255 需要八个二进制位(11111111)来表示。
八进制(基数 8)
八进制使用八个符号:0 到 7。每个八进制数字恰好代表三个二进制位,因此它是二进制数据的紧凑简写形式。八进制在字长为 12 位、24 位和 36 位的系统上尤为流行,因为这些字长能被 3 整除。
十进制(基数 10)
十进制使用十个符号:0 到 9。这是人类从小使用的日常数制。然而,十进制与二进制并不整齐对齐——不存在整数 n 使得 10 = 2^n——因此十进制转二进制需要反复做除法。
十六进制(基数 16)
十六进制使用十六个符号:0-9 和 A-F。每个十六进制数字恰好对应四个二进制位(因为 16 = 2^4)。十六进制在现代计算中占主导地位,广泛用于内存地址、颜色代码和字节级数据检查。关于十六进制转二进制,请参见我们的十六进制转二进制指南。
为什么二进制与八进制直接相关
二进制转八进制背后的关键洞见来自一个简单的数学事实:8 = 2³。由于八进制的基数是二进制基数的精确幂次,每个八进制数字对应固定数量的二进制位——确切地说,是三位。
这意味着:
- 八进制数字 0 = 二进制 000
- 八进制数字 1 = 二进制 001
- 八进制数字 7 = 二进制 111
三个二进制位的所有可能组合(恰好 2³ = 8 种)与八个八进制数字一一对应。这不是巧合,也不是近似,而是两种数制之间精确的结构性关系。
与十进制相比:将二进制转换为十进制需要位置运算,因为 10 不是 2 的幂次。而将二进制转换为八进制,只需分组和替换,别无其他。
同样的原理也适用于十六进制(16 = 2^4,因此每个十六进制数字 = 4 位),但不适用于以 5 或 12 为基数的数制,因为它们与 2 的幂次没有整除关系。
3 位分组法:分步详解
将二进制转换为八进制是一个三步机械过程。
第一步:从右向左将二进制数分成 3 位一组
取二进制数,从最右侧(最低有效位)开始,将其分成每组三位。
例如,二进制数 110101011:
1 | 101 | 011 (从右分组)
第二步:在最左侧的组前补零
如果最左侧的组不足三位,在其左侧补零以凑足三位。这不会改变数的值。
001 | 101 | 011 (补零后)
第三步:用对应的八进制数字替换每组 3 位
使用转换对照表(见下节)对每组进行替换:
- 001 = 1
- 101 = 5
- 011 = 3
结果: 二进制 110101011 = 八进制 153
这就是完整的算法。无需除法、无需取模运算、无需进位——只需分组、补零和替换。
3 位快速参考表(000-111)
这是二进制转八进制所需的核心查找表,只需记住八个条目:
| 二进制 | 八进制 | 十进制 |
|---|---|---|
| 000 | 0 | 0 |
| 001 | 1 | 1 |
| 010 | 2 | 2 |
| 011 | 3 | 3 |
| 100 | 4 | 4 |
| 101 | 5 | 5 |
| 110 | 6 | 6 |
| 111 | 7 | 7 |
由于八进制数字的范围是 0 到 7,这张表已经穷举了所有情况。一旦记住这八种映射关系,你就能在几秒内手工将任意二进制数转换为八进制。
实战示例
示例一:短二进制数(6 位)
二进制输入: 101110
第一步:从右分组:101 | 110
第二步:两组都已是 3 位,无需补零。
第三步:转换:
- 101 = 5
- 110 = 6
结果: 八进制 56(十进制 46)
示例二:完整字节(8 位)
二进制输入: 11010110
第一步:从右分组:11 | 010 | 110
第二步:在最左侧的组前补零:011 | 010 | 110
第三步:转换:
- 011 = 3
- 010 = 2
- 110 = 6
结果: 八进制 326(十进制 214)
注意,一个字节(8 位)总会产生两位或三位八进制数,因为 8 不能被 3 整除。这也是为什么面向字节的架构会更青睐十六进制(一个字节恰好等于两位十六进制数)而非八进制的原因之一。
示例三:奇数位二进制(5 位)
二进制输入: 10011
第一步:从右分组:10 | 011
第二步:补零:010 | 011
第三步:转换:
- 010 = 2
- 011 = 3
结果: 八进制 23(十进制 19)
示例四:长二进制数(16 位)
二进制输入: 1100100111010110
第一步:从右分组:1 | 100 | 100 | 111 | 010 | 110
第二步:补零:001 | 100 | 100 | 111 | 010 | 110
第三步:转换:
- 001 = 1
- 100 = 4
- 100 = 4
- 111 = 7
- 010 = 2
- 110 = 6
结果: 八进制 144726(十进制 51,670)
示例五:全为 1
二进制输入: 111111111(九个 1)
第一步:分组:111 | 111 | 111
第二步:无需补零(已对齐)。
第三步:转换:111 = 7,111 = 7,111 = 7
结果: 八进制 777(十进制 511)
这个值在 Unix 权限中意义重大——chmod 777 授予所有者、所属组和其他用户读、写、执行权限。
扩展转换表(0-127)
下表列出 0 到 127 的二进制、八进制和十进制值,涵盖完整的 7 位 ASCII 范围以及最常用的数值。
| 十进制 | 二进制 | 八进制 | 十进制 | 二进制 | 八进制 |
|---|---|---|---|---|---|
| 0 | 000 000 | 00 | 64 | 1 000 000 | 100 |
| 1 | 000 001 | 01 | 65 | 1 000 001 | 101 |
| 2 | 000 010 | 02 | 66 | 1 000 010 | 102 |
| 3 | 000 011 | 03 | 67 | 1 000 011 | 103 |
| 4 | 000 100 | 04 | 68 | 1 000 100 | 104 |
| 5 | 000 101 | 05 | 69 | 1 000 101 | 105 |
| 6 | 000 110 | 06 | 70 | 1 000 110 | 106 |
| 7 | 000 111 | 07 | 71 | 1 000 111 | 107 |
| 8 | 001 000 | 10 | 72 | 1 001 000 | 110 |
| 9 | 001 001 | 11 | 73 | 1 001 001 | 111 |
| 10 | 001 010 | 12 | 74 | 1 001 010 | 112 |
| 11 | 001 011 | 13 | 75 | 1 001 011 | 113 |
| 12 | 001 100 | 14 | 76 | 1 001 100 | 114 |
| 13 | 001 101 | 15 | 77 | 1 001 101 | 115 |
| 14 | 001 110 | 16 | 78 | 1 001 110 | 116 |
| 15 | 001 111 | 17 | 79 | 1 001 111 | 117 |
| 16 | 010 000 | 20 | 80 | 1 010 000 | 120 |
| 17 | 010 001 | 21 | 81 | 1 010 001 | 121 |
| 18 | 010 010 | 22 | 82 | 1 010 010 | 122 |
| 19 | 010 011 | 23 | 83 | 1 010 011 | 123 |
| 20 | 010 100 | 24 | 84 | 1 010 100 | 124 |
| 21 | 010 101 | 25 | 85 | 1 010 101 | 125 |
| 22 | 010 110 | 26 | 86 | 1 010 110 | 126 |
| 23 | 010 111 | 27 | 87 | 1 010 111 | 127 |
| 24 | 011 000 | 30 | 88 | 1 011 000 | 130 |
| 25 | 011 001 | 31 | 89 | 1 011 001 | 131 |
| 26 | 011 010 | 32 | 90 | 1 011 010 | 132 |
| 27 | 011 011 | 33 | 91 | 1 011 011 | 133 |
| 28 | 011 100 | 34 | 92 | 1 011 100 | 134 |
| 29 | 011 101 | 35 | 93 | 1 011 101 | 135 |
| 30 | 011 110 | 36 | 94 | 1 011 110 | 136 |
| 31 | 011 111 | 37 | 95 | 1 011 111 | 137 |
| 32 | 100 000 | 40 | 96 | 1 100 000 | 140 |
| 33 | 100 001 | 41 | 97 | 1 100 001 | 141 |
| 34 | 100 010 | 42 | 98 | 1 100 010 | 142 |
| 35 | 100 011 | 43 | 99 | 1 100 011 | 143 |
| 36 | 100 100 | 44 | 100 | 1 100 100 | 144 |
| 37 | 100 101 | 45 | 101 | 1 100 101 | 145 |
| 38 | 100 110 | 46 | 102 | 1 100 110 | 146 |
| 39 | 100 111 | 47 | 103 | 1 100 111 | 147 |
| 40 | 101 000 | 50 | 104 | 1 101 000 | 150 |
| 41 | 101 001 | 51 | 105 | 1 101 001 | 151 |
| 42 | 101 010 | 52 | 106 | 1 101 010 | 152 |
| 43 | 101 011 | 53 | 107 | 1 101 011 | 153 |
| 44 | 101 100 | 54 | 108 | 1 101 100 | 154 |
| 45 | 101 101 | 55 | 109 | 1 101 101 | 155 |
| 46 | 101 110 | 56 | 110 | 1 101 110 | 156 |
| 47 | 101 111 | 57 | 111 | 1 101 111 | 157 |
| 48 | 110 000 | 60 | 112 | 1 110 000 | 160 |
| 49 | 110 001 | 61 | 113 | 1 110 001 | 161 |
| 50 | 110 010 | 62 | 114 | 1 110 010 | 162 |
| 51 | 110 011 | 63 | 115 | 1 110 011 | 163 |
| 52 | 110 100 | 64 | 116 | 1 110 100 | 164 |
| 53 | 110 101 | 65 | 117 | 1 110 101 | 165 |
| 54 | 110 110 | 66 | 118 | 1 110 110 | 166 |
| 55 | 110 111 | 67 | 119 | 1 110 111 | 167 |
| 56 | 111 000 | 70 | 120 | 1 111 000 | 170 |
| 57 | 111 001 | 71 | 121 | 1 111 001 | 171 |
| 58 | 111 010 | 72 | 122 | 1 111 010 | 172 |
| 59 | 111 011 | 73 | 123 | 1 111 011 | 173 |
| 60 | 111 100 | 74 | 124 | 1 111 100 | 174 |
| 61 | 111 101 | 75 | 125 | 1 111 101 | 175 |
| 62 | 111 110 | 76 | 126 | 1 111 110 | 176 |
| 63 | 111 111 | 77 | 127 | 1 111 111 | 177 |
你可以使用我们的二进制转八进制工具验证其中任意数值。
八进制转回二进制
反向过程——八进制转二进制——同样简单直接。只需将每个八进制数字替换为对应的 3 位二进制值即可。
逆向转换步骤
- 写下八进制数。 去掉前缀符号(如 C/C++ 中的前导
0,或 Python 中的0o)。 - 将每个八进制数字替换为对应的 3 位二进制值。 使用上方同一张 8 条目查找表。
- 将各组拼接起来。 结果即为完整的二进制表示。
- 去掉前导零(可选),得到最简二进制形式。
实战示例:八进制 375 转二进制
八进制输入: 375
- 3 = 011
- 7 = 111
- 5 = 101
结果: 011111101,或去掉前导零后为 11111101(十进制 253)
实战示例:八进制 52 转二进制
八进制输入: 52
- 5 = 101
- 2 = 010
结果: 101010(十进制 42)
这种双向转换的简洁性,正是 2³ = 8 这一关系的直接体现。转换无损、精确,无需任何算术运算。
编程示例
Python
Python 对八进制和二进制提供内置支持:
# 基本的二进制转八进制
binary_str = "110101011"
decimal_value = int(binary_str, 2)
octal_str = oct(decimal_value) # '0o653'
# 去掉前缀的输出
clean_octal = oct(decimal_value)[2:] # '653'
# 单行写法
def bin_to_oct(b):
return oct(int(b, 2))[2:]
# 手动使用 3 位分组法
def bin_to_oct_manual(binary):
# 补零至 3 的倍数
while len(binary) % 3 != 0:
binary = '0' + binary
# 分组并转换
octal = ''
for i in range(0, len(binary), 3):
group = binary[i:i+3]
octal += str(int(group, 2))
return octal
print(bin_to_oct_manual("110101011")) # '653'
print(bin_to_oct_manual("11111111")) # '377'
JavaScript
JavaScript 使用 parseInt() 和 .toString() 进行进制转换:
// 基本的二进制转八进制
const binary = "110101011";
const octal = parseInt(binary, 2).toString(8); // '653'
// 带输入校验的函数
function binaryToOctal(bin) {
if (!/^[01]+$/.test(bin)) {
throw new Error("Invalid binary string");
}
return parseInt(bin, 2).toString(8);
}
// 手动 3 位分组法
function binaryToOctalManual(binary) {
// 补零至 3 的倍数
while (binary.length % 3 !== 0) {
binary = "0" + binary;
}
let octal = "";
for (let i = 0; i < binary.length; i += 3) {
const group = binary.substring(i, i + 3);
octal += parseInt(group, 2).toString();
}
return octal;
}
console.log(binaryToOctalManual("110101011")); // '653'
console.log(binaryToOctalManual("111101101")); // '755'
C
C 没有内置的字符串进制转换,需要手动实现:
#include <stdio.h>
#include <string.h>
void binaryToOctal(const char *binary) {
int len = strlen(binary);
// 计算补零至 3 的倍数所需的位数
int padding = (3 - (len % 3)) % 3;
int totalLen = len + padding;
// 创建补零后的二进制字符串
char padded[65];
memset(padded, '0', padding);
strcpy(padded + padding, binary);
// 转换每组 3 位
printf("Binary %s = Octal ", binary);
for (int i = 0; i < totalLen; i += 3) {
int value = (padded[i] - '0') * 4
+ (padded[i+1] - '0') * 2
+ (padded[i+2] - '0');
printf("%d", value);
}
printf("\n");
}
int main() {
binaryToOctal("110101011"); // 八进制 653
binaryToOctal("111101101"); // 八进制 755
binaryToOctal("11111111"); // 八进制 377
binaryToOctal("1"); // 八进制 1
return 0;
}
三种实现产生相同的结果。手动分组法与手工转换的过程完全一致,而内置函数(Python 的 oct()、JavaScript 的 .toString(8))则在内部完成分组。
实际应用:Unix/Linux 文件权限
八进制数在现代计算中最常见的日常应用是 Unix/Linux 文件权限。如果你曾在终端输入过 chmod 755 script.sh,你就已经用到了二进制转八进制——无论你当时是否意识到。
Unix 权限的工作原理
Unix 类系统中的每个文件和目录都有三组权限:
- 所有者(创建文件的用户)
- 所属组(文件所属组的用户)
- 其他用户(所有其他人)
每组都有三个权限标志:
| 权限 | 符号 | 二进制位 | 值 |
|---|---|---|---|
| 读取 | r | 1 | 4 |
| 写入 | w | 1 | 2 |
| 执行 | x | 1 | 1 |
每组三个权限恰好对应 3 个二进制位,也恰好对应 1 个八进制数字。这并非巧合——选择八进制正是因为它与 3 位权限组完美对齐。
解读 chmod 755
八进制数 755 分解如下:
| 对象 | 八进制 | 二进制 | 权限 | 含义 |
|---|---|---|---|---|
| 所有者 | 7 | 111 | rwx | 读取 + 写入 + 执行 |
| 所属组 | 5 | 101 | r-x | 读取 + 执行 |
| 其他用户 | 5 | 101 | r-x | 读取 + 执行 |
因此 chmod 755 将完整的二进制权限掩码设置为 111 101 101,赋予所有者完全控制权,同时允许其他所有人读取和执行,但不允许修改文件。
常用权限值
| 八进制 | 二进制 | 符号表示 | 典型用途 |
|---|---|---|---|
| 777 | 111 111 111 | rwxrwxrwx | 所有人完全访问(存在风险) |
| 755 | 111 101 101 | rwxr-xr-x | 可执行脚本、目录 |
| 750 | 111 101 000 | rwxr-x--- | 组内可访问的可执行文件 |
| 700 | 111 000 000 | rwx------ | 私有可执行文件 |
| 644 | 110 100 100 | rw-r--r-- | 普通文件(Web 内容) |
| 600 | 110 000 000 | rw------- | 私有文件(SSH 密钥) |
| 400 | 100 000 000 | r-------- | 只读文件(证书) |
理解二进制转八进制,能让 chmod 的值变得直观,而非神秘莫测。
八进制在计算历史与现代使用中的地位
历史意义
八进制符号在早期计算中占主导地位,有其实际原因:许多早期计算机使用的字长是 3 的倍数。PDP-8(12 位字)、UNIVAC 1108(36 位字)和 IBM 7090(36 位字)都采用了八进制作为自然的紧凑记数法。12 位字恰好对应四个八进制数字,36 位字对应十二个八进制数字。
C 语言中的八进制前缀 0 正是这个时代的直接遗产——Ken Thompson 和 Dennis Ritchie 在 PDP-11 上开发 C 语言时,八进制记数法是贝尔实验室的标准。这一约定延续至今,在 C、C++、Java 等语言中仍然存在(例如,C 中的 0755 是八进制 755,十进制 493)。
为什么十六进制基本取代了八进制
从八进制到十六进制的转变,发生在行业以 8 位字节为标准化单位的时期。由于 8 不能被 3 整除,一个字节无法整齐地映射到整数个八进制数字(需要 2.67 个八进制数字)。相比之下,一个字节恰好对应两个十六进制数字。随着字节寻址架构(Intel 8080、Zilog Z80、Motorola 68000)成为主流,十六进制取代八进制成为首选记数法。
八进制今日仍在使用的领域
尽管十六进制占据主导,八进制在以下几个领域仍然相关:
- Unix/Linux 文件权限:
chmod、umask和stat均使用八进制 - C/C++ 八进制字面量:以前导
0开头的整数字面量(如0755)被解释为八进制 - Python 八进制字面量:使用
0o前缀(如0o755) - 转义序列:部分编程语言使用
\nnn(八进制)作为字符转义 - 航空应答机代码:飞机的应答码是四位八进制数(0000-7777)
- 遗留系统:20 世纪 60-70 年代的大型机代码和文档中频繁使用八进制
常见问题
如何将二进制转换为八进制?
从右向左将二进制位分成每组三位,必要时在最左侧的组前补零。然后将每组 3 位替换为对应的八进制数字(000=0、001=1、010=2、011=3、100=4、101=5、110=6、111=7)。例如,二进制 11010110 分组为 011 010 110,转换结果为八进制 326。
为什么二进制转八进制要以 3 位为一组?
因为 8 = 2³。八进制的基数(8)是二进制基数(2)的三次方,这意味着恰好需要三个二进制位才能表示一个八进制数字的所有可能值(0 到 7)。这种数学关系使转换成为直接替换,无需任何算术运算。
二进制 11111111 的八进制是多少?
二进制 11111111(十进制 255)转换为八进制 377。从右分组:011 111 111,得到 3-7-7。这是一个字节在八进制表示法中的最大值。
位数不是 3 的倍数的二进制数应该如何处理?
在最左侧的组前补零。例如,二进制 10011 有 5 位,从右分组:10 011;左侧补零:010 011;转换结果:2-3,即八进制 23。补前导零不会改变数值。
八进制和十六进制有什么区别?
八进制是以 8 为基数(数字 0-7),每个数字代表 3 个二进制位。十六进制是以 16 为基数(数字 0-9、A-F),每个数字代表 4 个二进制位。十六进制在现代计算中更为常见,因为它与 8 位字节对齐(2 个十六进制数字 = 1 个字节),而八进制仍用于 Unix 文件权限和遗留系统。
chmod 为什么使用八进制数字?
每个文件权限组(所有者、所属组、其他用户)由三个二进制标志组成:读取(r)、写入(w)和执行(x)。三个二进制标志直接对应一个八进制数字(因为 2³ = 8)。这使八进制成为表达 Unix 权限最自然、最紧凑的记数法。例如,rwxr-xr-x = 111 101 101 = 八进制 755。
可以直接将八进制转换为二进制吗?
可以——只需将每个八进制数字替换为对应的 3 位二进制值即可。八进制 47 转换为 100 111(二进制)。这一过程与二进制转八进制完全相反,同样机械化。无需除法或乘法。
八进制 777 对应的二进制和十进制是多少?
八进制 777 等于二进制 111 111 111(九个 1)和十进制 511。在 Unix 权限中,chmod 777 授予所有者、所属组和所有其他用户完全的读、写、执行权限。
小结
二进制转八进制依赖一个基础事实:8 = 2³,因此每个八进制数字恰好对应三个二进制位。无论转换的是 3 位值还是 64 位地址,算法始终相同:从右向左三位分组,对最左侧的组补零,然后逐组替换。
本指南的核心要点:
- 从右向左将二进制位分成 3 位一组,然后将每组替换为对应的八进制数字(000-111 对应 0-7)
- 位数不是 3 的倍数时,在最左侧的组前补零
- Unix 文件权限是八进制最常见的现代用途,每组 rwx 权限对应一个八进制数字
- 编程语言提供内置转换:Python 的
oct(int(x, 2))、JavaScript 的parseInt(x, 2).toString(8),以及 C 中的手动分组实现 - 逆向转换(八进制转二进制)通过将每个八进制数字替换为对应的 3 位二进制值来实现
- 八进制曾在字长为 3 的倍数的系统上占主导地位,但随着 8 位字节成为标准,十六进制取而代之
准备好练习了吗?使用我们的免费二进制转八进制工具,即时将任意二进制值转换为八进制,并获得 3 位分组可视化展示和自动补零功能。