在计算机科学和数字逻辑中,二进制(Base-2)和八进制(Base-8)是两种常见的数制,虽然现代编程中八进制使用频率不如十六进制高,但在权限管理(如Linux文件权限)、底层系统编程以及某些嵌入式场景中,八进制仍有一席之地,理解二进制转八进制的方法,不仅能加深对数制转换本质的认识,还能提升手动与编程计算的能力。

本文将系统讲解二进制转八进制的原理、手动转换步骤、快速心算技巧,并提供Python与C语言的代码示例,帮助你彻底掌握这一技能。
为什么要用八进制?
在深入转换方法之前,先回答一个基本问题:既然已经有二进制和十六进制,为什么还要八进制?
- 简洁表示:二进制太长,而八进制比二进制短,且每位八进制对应3位二进制,分组非常整齐。
- 历史遗留:早期计算机(如PDP-8)采用12位或24位字长,能被3整除,八进制自然成为首选。
- 权限管理:Linux/Unix系统中,文件权限用三位八进制数(如
755)表示,每位对应rwx,这源于八进制与二进制的直接对应关系。
核心原理:3位二进制对应1位八进制
八进制共有8个数字(0~7),而3位二进制恰好能表示0~7的所有组合(2³=8)。从二进制到八进制的转换,本质上是将二进制数按每3位一组进行分组,然后将每组转换成一个八进制数字。
| 3位二进制 | 八进制数字 |
|---|---|
| 000 | 0 |
| 001 | 1 |
| 010 | 2 |
| 011 | 3 |
| 100 | 4 |
| 101 | 5 |
| 110 | 6 |
| 111 | 7 |
这个对应表是所有转换的基础,建议牢记。
手动转换步骤(整数与小数)
1 整数部分转换
步骤:
- 从最右边(最低位)开始,向左每3位二进制数字为一组。
- 如果最左边的组不足3位,则在左侧补0(最左边补0不会改变数值)。
- 对照上表,将每组3位二进制转换为对应的八进制数字。
- 从左到右写出所有八进制数字,即为结果。
示例1:将二进制110101转换为八进制
- 从右向左分组:
110 101✅ 正好两组,每组3位。 110→ 6,101→ 5- 结果:
65(八进制)
示例2:将二进制10110转换为八进制
- 从右向左分组:
10 110← 从右开始,左边只有2位。 - 补足3位:
010 110← 左侧补一个0。 010→ 2,110→ 6- 结果:
26(八进制)
2 小数部分转换
步骤:
- 从最左边(最高位)开始,向右每3位二进制数字为一组。
- 如果最右边的组不足3位,则在右侧补0(小数点后右侧补0不会改变数值)。
- 每组转换为对应的八进制数字,小数点的位置保持不变。
示例3:将二进制1101转换为八进制
- 从小数点后第一位开始,向右分组:
110 1← 最后一组只有1位。 - 补足3位:
110 100← 右侧补两个0。 110→ 6,100→ 4- 结果:
64(八进制)
3 同时包含整数和小数
整数部分和小数部分分别处理,中间用小数点连接。
示例4:将二进制0011转换为八进制
- 整数部分(向左分组):
10 101→010 101→ 2, 5 →25 - 小数部分(向右分组):
001 1→001 100→ 1, 4 →14 - 结果:
14(八进制)
快速心算技巧
如果你熟悉8以内的二进制值,可以直接心算:
- 记住表头:
000→0, 001→1, 010→2, 011→3, 100→4, 101→5, 110→6, 111→7 - 练习方法:随机写一个二进制数(如
111001010),从左到右每三位一读:111→7, 001→1, 010→2→ 八进制712。 - 多做几次,熟练后速度极快。
编程实现(Python与C)
1 Python实现
Python内置了oct()函数,可以直接将整数(十进制或二进制形式)转换为八进制字符串。
# 使用内置函数 binary_str = "110101" decimal = int(binary_str, 2) # 先转十进制 octal_str = oct(decimal) # 转八进制,输出如 '0o65' print(octal_str[2:]) # 去掉前缀 '0o',输出 '65'
如果不想依赖内置函数,可以手动实现分组转换:
def bin_to_oct(binary_str):
# 去除可能的 '0b' 前缀
if binary_str.startswith('0b'):
binary_str = binary_str[2:]
# 处理整数部分和小数部分
if '.' in binary_str:
int_part, frac_part = binary_str.split('.')
else:
int_part, frac_part = binary_str, ''
# 整数部分:从右向左每3位分组
while len(int_part) % 3 != 0:
int_part = '0' + int_part
int_groups = [int_part[i:i+3] for i in range(0, len(int_part), 3)]
int_oct = ''.join(str(int(g, 2)) for g in int_groups)
# 小数部分:从左向右每3位分组
if frac_part:
while len(frac_part) % 3 != 0:
frac_part += '0'
frac_groups = [frac_part[i:i+3] for i in range(0, len(frac_part), 3)]
frac_oct = ''.join(str(int(g, 2)) for g in frac_groups)
return int_oct + '.' + frac_oct
return int_oct
# 测试
print(bin_to_oct('110101')) # 输出 '65'
print(bin_to_oct('0b10110')) # 输出 '26'
print(bin_to_oct('0.1101')) # 输出 '0.64'
print(bin_to_oct('10101.0011')) # 输出 '25.14'
2 C语言实现
C语言标准库没有直接转换函数,需要手动实现。
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
// 将3位二进制字符串转换为整数
int bin3_to_int(const char *s) {
int val = 0;
for (int i = 0; i < 3; i++) {
val = val * 2 + (s[i] - '0');
}
return val;
}
// 二进制转八进制(整数部分)
void bin_to_oct_int(const char *bin, char *oct) {
int len = strlen(bin);
// 补齐左侧0,使长度为3的倍数
int pad = (3 - len % 3) % 3;
char padded[100];
int idx = 0;
for (int i = 0; i < pad; i++) padded[idx++] = '0';
for (int i = 0; i < len; i++) padded[idx++] = bin[i];
padded[idx] = '\0';
// 每3位一组转换
int groups = strlen(padded) / 3;
for (int i = 0; i < groups; i++) {
char group[4];
strncpy(group, padded + i * 3, 3);
group[3] = '\0';
oct[i] = bin3_to_int(group) + '0';
}
oct[groups] = '\0';
}
// 二进制转八进制(支持小数)
void bin_to_oct(const char *bin, char *oct) {
char int_part[100], frac_part[100];
int has_frac = 0;
// 分离整数和小数
const char *dot = strchr(bin, '.');
if (dot) {
has_frac = 1;
strncpy(int_part, bin, dot - bin);
int_part[dot - bin] = '\0';
strcpy(frac_part, dot + 1);
} else {
strcpy(int_part, bin);
frac_part[0] = '\0';
}
char int_oct[50] = "";
bin_to_oct_int(int_part, int_oct);
if (has_frac) {
// 小数部分:从左向右补0,每3位一组
int len = strlen(frac_part);
int pad = (3 - len % 3) % 3;
char padded_frac[100];
strcpy(padded_frac, frac_part);
for (int i = 0; i < pad; i++) {
padded_frac[len + i] = '0';
}
padded_frac[len + pad] = '\0';
char frac_oct[50] = "";
int groups = strlen(padded_frac) / 3;
for (int i = 0; i < groups; i++) {
char group[4];
strncpy(group, padded_frac + i * 3, 3);
group[3] = '\0';
frac_oct[i] = bin3_to_int(group) + '0';
}
frac_oct[groups] = '\0';
sprintf(oct, "%s.%s", int_oct, frac_oct);
} else {
strcpy(oct, int_oct);
}
}
int main() {
char result[100];
bin_to_oct("110101", result);
printf("110101 -> %s\n", result); // 输出 65
bin_to_oct("10110", result);
printf("10110 -> %s\n", result); // 输出 26
bin_to_oct("0.1101", result);
printf("0.1101 -> %s\n", result); // 输出 0.64
bin_to_oct("10101.0011", result);
printf("10101.0011 -> %s\n", result); // 输出 25.14
return 0;
}
常见错误与注意事项
- 分组方向搞反:整数从右向左,小数从左向右,整数右对齐,小数左对齐”。
- 补0位置错误:整数补在左侧,小数补在右侧,补0的目的是为了让每组恰好3位。
- 八进制前缀:在编程中,八进制字面量通常以
0o或0开头(如Python的0o65,C语言的065),但手动书写时有时忽略前缀,注意上下文。 - 八进制中没有8和9:转换时如果某组二进制超过
111(即十进制7),说明输入有误。 - 八进制与十进制混淆:例如
65(八进制)表示6×8 + 5 = 53(十进制),而非65。
二进制转八进制的核心是“3位合1位”的分组映射法,无论手动计算还是编程实现,只要掌握分组方向与补0规则,就能快速准确转换,这一技能不仅是数制转换的基础,也是理解计算机底层数据表示的重要一环。
建议读者用几个随意写的二进制数练习(如11100101、101011),对照本文的方法验证结果,直到形成肌肉记忆,当你能在5秒内心算出1101的八进制结果时,你就真正掌握了。
延伸思考:如果让你实现二进制转十六进制,你会如何设计?提示:十六进制对应4位一组(2⁴=16),方法完全对称,掌握一种,便能举一反三。

