二进制、八进制、十六进制相互转换:原理、技巧与实战应用

发布时间:2026/9/23 12:14:11
二进制、八进制、十六进制相互转换:原理、技巧与实战应用
1. 为什么值得花时间搞懂进制转换很多人第一次接触二进制、八进制、十六进制是在计算机基础课上。老师讲了一遍“逢二进一”“逢八进一”“逢十六进一”然后给了一堆练习题做完就忘了。等到真正需要用到的时候——比如看一个二进制文件头、分析一段内存数据、手算一个校验码、调一个嵌入式寄存器配置——才发现脑子里只剩一个模糊的印象连217转成二进制都要掏手机。这篇文章想做的事情很直接把二进制、八进制、十六进制之间的相互转换讲透不是那种“背公式”的讲法而是从“为什么这样转”出发把每一步的计算逻辑摊开给你看。不管你是刚学计算机基础的学生还是工作几年后突然需要跟底层数据打交道的开发者或者是准备考试、打CTF的选手这里的内容都能直接拿去用。核心关键词就四个二进制、十六进制、八进制、相互转换。围绕这四个词我会把转换的原理、手算方法、快速技巧、常见坑点、实际应用场景全部串起来。你看完之后至少能做到拿到一个十进制数三秒内反应出它的二进制大概长什么样看到一串十六进制能立刻拆成二进制遇到八进制和二进制混用的场景不会慌。先说一个最基本的认知进制本身只是表示方法不改变数值大小。同一个数用十进制写是217用二进制写是11011001用八进制写是331用十六进制写是D9。它们说的是同一件事只是“语言”不同。转换的本质就是把这几种语言互相翻译。那为什么计算机领域偏偏要用这几种进制原因很简单二进制是硬件能直接理解的语言电路的通断、电平的高低天然就是两种状态。八进制和十六进制则是为了方便人类读写二进制而存在的“压缩格式”。一位八进制对应三位二进制一位十六进制对应四位二进制。这个对应关系是理解所有转换技巧的钥匙。记住这句话八进制是二进制的“三位一组压缩”十六进制是二进制的“四位一组压缩”。所有转换技巧都从这个关系推导出来。2. 二进制与其他进制转换的底层逻辑2.1 二进制的本质位置记数法要搞懂转换先得搞懂二进制本身是怎么表示数的。十进制我们太熟了217 2×10² 1×10¹ 7×10⁰。每一位的权重是10的幂次。二进制一模一样只不过权重变成2的幂次。以11011001为例从右往左每一位的权重分别是位置从右数76543210权重2的幂1286432168421该位数字11011001把数字为1的位对应的权重加起来128 64 16 8 1 217。这就是二进制转十进制的核心方法——按权重展开求和。反过来十进制转二进制就是不断地“拆出最大的2的幂”。217最接近的2的幂是1282⁷剩下8989拆出642⁶剩下2525拆出162⁴剩下99拆出82³剩下11就是2⁰。所以217 128641681对应二进制11011001。这个方法叫降幂法适合手算尤其是数字不太大的时候。但数字大了就麻烦所以还有另一个更机械的方法除2取余法。217除以2得108余1108除以2得54余054除以2得27余027除以2得13余113除以2得6余16除以2得3余03除以2得1余11除以2得0余1。把余数从下往上读11011001。结果一致。实操心得手算十进制转二进制时如果数字在256以内用降幂法更快因为2的幂次表你基本能背下来。如果数字很大除2取余法更稳妥不容易出错。2.2 八进制与十六进制的“压缩”逻辑八进制和十六进制之所以存在纯粹是因为二进制写起来太长。一个32位的寄存器值用二进制写是32个0和1眼睛都要看花。用十六进制写只有8位清爽得多。它们之间的对应关系是固定的1位八进制 3位二进制因为2³ 81位十六进制 4位二进制因为2⁴ 16这个关系意味着二进制转八进制或十六进制根本不需要经过十进制中转。直接分组就行。二进制转八进制从右往左每3位一组不足3位的左边补0。比如11011001从右往左分组011 011 001。每组转成对应的八进制数字011301130011。结果是331。二进制转十六进制从右往左每4位一组不足4位的左边补0。11011001分组1101 1001。1101D1310019。结果是D9。反过来八进制转二进制把每一位八进制展开成3位二进制就行。331展开301130111001拼起来011011001去掉前导0就是11011001。十六进制转二进制同理D9展开D110191001拼起来11011001。这套“分组展开”的方法比经过十进制中转快得多而且不容易出错。核心技巧就是记住那张对应表十六进制二进制八进制二进制0000000001000110012001020103001130114010041005010151016011061107011171118100091001A1010B1011C1100D1101E1110F1111这张表建议直接背下来。背下来之后二进制和八进制、十六进制之间的转换基本就是“查表拼接”的体力活不需要动脑子算。2.3 八进制与十六进制之间的转换路径八进制和十六进制之间直接转换没有像“3位一组”“4位一组”那样简单的对应关系因为8和16不是幂次关系。最可靠的方法是以二进制为桥梁先把八进制转成二进制再把二进制转成十六进制或者反过来。比如八进制331转十六进制331先展开成二进制011011001去掉前导0得11011001再按4位分组1101 1001得D9。反过来D9转八进制D9展开成11011001按3位分组011 011 001得331。有人会问能不能先用十进制中转可以但多了一步而且十进制转换容易出错。以二进制为桥梁是最短路径也是最不容易出错的方式。注意事项分组时一定要从右往左分不足的位在左边补0。如果从左往右分最后的结果会完全错误。这是初学者最容易犯的错误之一。3. 手算转换的实操技巧与快速方法3.1 十进制转二进制的两种手算方法对比前面提到了降幂法和除2取余法这里展开说一下各自的适用场景和操作细节。降幂法的操作步骤先列出2的幂次表1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024...然后从最大的不超过目标数的幂开始依次尝试减去。能减就记1不能减就记0。以217为例128能减记1剩8964能减记1剩2532不能减记016能减记1剩98能减记1剩14不能减记02不能减记01能减记1剩0。结果11011001。这个方法的好处是直观你能清楚地看到每一位的权重适合理解二进制的本质。缺点是数字大了之后2的幂次表要列很长而且减法容易算错。除2取余法的操作步骤不断除以2记录余数直到商为0然后倒序读取余数。217÷2108余1108÷254余054÷227余027÷213余113÷26余16÷23余03÷21余11÷20余1。倒序读11011001。这个方法的好处是机械不需要记2的幂次表适合数字较大的情况。缺点是步骤多容易在中间某一步算错。方法适用场景优点缺点降幂法数字≤256需要理解原理直观能看到权重大数时幂次表太长除2取余法任意大小数字机械不需要记表步骤多易算错实操心得我个人的习惯是数字在128以内用降幂法超过128用除2取余法。另外除2取余法可以用“连续除以2”的方式加速比如217连续除以2三次得27余1、0、0可以直接写出低三位是001。3.2 二进制转十进制的快速心算技巧二进制转十进制核心是“按权重求和”。但手算时不需要每次都把所有权重列出来。有几个快速技巧技巧一从高位往低位累加。以11011001为例从左往右遇到1就“当前值×21”遇到0就“当前值×2”。具体过程1→11→1×2130→3×261→6×21131→13×21270→27×2540→54×21081→108×21217。这个方法叫霍纳法则不需要记权重只需要不断地“乘2加当前位”。技巧二记住几个关键权重。128、64、32、16、8、4、2、1这八个权重对应一个字节的8位。看到8位二进制直接对应权重相加就行。比如110110011在128、64、16、8、1的位置加起来217。技巧三分组计算。如果二进制很长可以每4位一组转成十六进制再把十六进制转十进制。比如11011001分成1101和1001分别是D和9D9转十进制13×169217。这个方法在二进制超过8位时特别有用。3.3 八进制和十六进制的“分组展开”实操二进制转八进制和十六进制的操作核心就是“分组查表”。但实际操作中有几个细节需要注意。分组方向必须从右往左分。因为二进制的低位对应数值的小端分组必须从低位开始才能保证每组的权重是3或4的整数倍。如果从左往右分最高位那组可能不足3位或4位补0的位置就错了。补0规则不足一组时在左边补0。比如二进制1011转八进制从右往左每3位一组1 011左边不足3位补0得001 011即13。如果补在右边变成011 010结果是32完全错了。前导0的处理转换结果中最高位的0可以去掉。比如011011001转八进制是331前面的0去掉。但中间和末尾的0不能去。十六进制字母的大小写A-F可以大写也可以小写不影响数值。但在编程中通常用大写表示十六进制常量比如0xD9。在十六进制编辑器中通常用小写比如d9。注意事项在十六进制编辑器中查看文件时经常看到类似“moz_require_signingtrue”这样的字符串。这其实是ASCII码的十六进制表示每个字符对应一个字节。比如‘m’的ASCII码是109十六进制是6D。看到这种内容不要慌按字节拆开查ASCII表就行。3.4 八进制与十六进制互转的“二进制桥梁法”八进制和十六进制直接互转最可靠的方法是以二进制为桥梁。具体步骤把源进制每一位展开成对应的二进制位八进制展开成3位十六进制展开成4位把得到的二进制串按目标进制的分组大小重新分组目标八进制按3位分目标十六进制按4位分每组查表转换成目标进制的数字以八进制331转十六进制为例331展开成011 011 001拼起来011011001去掉前导0得11011001。按4位分组1101 1001查表得D9。以十六进制D9转八进制为例D9展开成1101 1001拼起来11011001。按3位分组011 011 001查表得331。这个方法的好处是不需要经过十进制减少了出错的机会。而且二进制作为中间格式展开和分组都是机械操作不容易算错。转换方向展开规则分组规则示例八进制→十六进制每位展开成3位二进制按4位分组331→11011001→D9十六进制→八进制每位展开成4位二进制按3位分组D9→11011001→3314. 实际应用场景中的进制转换4.1 文件十六进制查看与二进制分析做安全分析、逆向工程、或者单纯想看看一个文件的内部结构时十六进制编辑器是必备工具。常见的文件开头都有固定的“魔数”比如PNG文件开头是89 50 4E 47JPEG文件开头是FF D8 FFZIP文件开头是50 4B 03 04。这些魔数用十六进制表示方便识别文件类型。当你用十六进制编辑器打开一个文件看到的内容全是十六进制数字。如果你想理解某个字节的含义就需要把它转成二进制看看每一位是什么。比如一个字节是0x8F转成二进制是10001111你可以看到最高位是1低4位是1111。这种位级别的分析在解析协议格式、分析寄存器配置、理解压缩算法时非常常见。有时候会遇到“十六进制文件全反了”的情况比如字节序问题。大端序和小端序的区别本质上就是字节的排列顺序不同。一个32位整数0x12345678在大端序中存储为12 34 56 78在小端序中存储为78 56 34 12。看到“全反了”的数据第一反应应该是检查字节序。实操心得在十六进制编辑器中搜索字符串时注意字符串的编码方式。ASCII字符串直接对应十六进制比如“moz_require_signingtrue”对应的十六进制是6D 6F 7A 5F 72 65 71 75 69 72 65 5F 73 69 67 6E 69 6E 67 3D 74 72 75 65。但如果是UTF-8编码的中文每个字符可能占3个字节搜索时要注意。4.2 嵌入式开发中的寄存器配置嵌入式开发中寄存器的配置通常以十六进制或二进制表示。比如一个8位的控制寄存器每一位代表一个功能开关。你需要根据需求把对应的位置1或置0然后转成十六进制写入。假设一个寄存器的定义如下bit7使能bit6中断bit5-4模式选择bit3保留bit2-0分频系数。如果你需要使能、开启中断、模式选择为10、分频系数为5那么二进制是1 1 10 0 101即11100101转成十六进制是0xE5。这种位操作的场景二进制和十六进制的转换是家常便饭。关键是要养成“按位思考”的习惯看到十六进制能立刻反应出二进制的位模式。4.3 校验码计算中的进制转换LRC校验码的计算过程中经常需要把数据转成二进制进行异或运算。比如计算一串十六进制数据的LRC校验码步骤通常是把所有字节相加取反加1或者进行异或运算。这些运算在二进制层面进行但输入和输出通常用十六进制表示。以LRC为例假设数据是01 03 00 00 00 01计算LRC的步骤是01030000000105取反得FA加1得FB。所以LRC是FB。这个过程涉及十六进制加法和二进制取反进制转换贯穿始终。注意事项计算校验码时注意数据的字节序和位序。有些协议规定高位在前有些规定低位在前。搞错了位序校验码就会算错。4.4 编程中的进制表示与转换在C语言中二进制没有直接的字面量表示C23之前但可以用十六进制或八进制表示。0x前缀表示十六进制0前缀表示八进制。比如0xD9是2170331也是217。在Python中二进制用0b前缀八进制用0o前缀十六进制用0x前缀。转换函数有bin()、oct()、hex()分别把整数转成二进制、八进制、十六进制字符串。# Python中的进制转换示例 n 217 print(bin(n)) # 0b11011001 print(oct(n)) # 0o331 print(hex(n)) # 0xd9 # 反向转换 print(int(11011001, 2)) # 217 print(int(331, 8)) # 217 print(int(d9, 16)) # 217在C语言中可以用strtol函数把字符串转成整数指定进制基数。#include stdlib.h #include stdio.h int main() { char *bin 11011001; char *oct 331; char *hex d9; printf(%ld\n, strtol(bin, NULL, 2)); // 217 printf(%ld\n, strtol(oct, NULL, 8)); // 217 printf(%ld\n, strtol(hex, NULL, 16)); // 217 return 0; }实操心得在C语言中strstr()函数不能用于查找二进制内存因为二进制数据中可能包含0字节而strstr()以0字节作为字符串结束标志。查找二进制内存要用memmem()或者自己写循环比较。5. 常见问题与避坑指南5.1 进制转换中的典型错误错误一分组方向搞反。二进制转八进制或十六进制时必须从右往左分组。从左往右分组会导致权重错位结果完全错误。这个错误在初学者中非常普遍尤其是在手算时容易忽略。错误二补0位置搞错。不足一组时在左边补0不是在右边。左边补0不改变数值大小右边补0相当于乘以2的幂次会改变数值。错误三十六进制字母混淆。A10B11C12D13E14F15。不要记错。尤其是B和D容易搞混。错误四十进制转二进制时余数顺序搞反。除2取余法得到的余数要从下往上读不是从上往下读。从上往下读得到的是反序的二进制。错误五忽略前导0。在编程中前导0可能表示八进制。比如C语言中010是八进制的8不是十进制的10。这个坑很多人踩过。错误类型错误做法正确做法后果分组方向从左往右分从右往左分结果完全错误补0位置右边补0左边补0数值改变余数顺序从上往下读从下往上读二进制反序前导0忽略注意八进制含义编程中数值错误5.2 小数部分的进制转换前面讲的都是整数的转换。小数部分的转换方法不同。十进制小数转二进制用“乘2取整法”不断乘以2取整数部分直到小数部分为0或达到精度要求。以0.6为例0.6×21.2取整1小数0.20.2×20.4取整0小数0.40.4×20.8取整0小数0.80.8×21.6取整1小数0.60.6×21.2取整1小数0.2……可以看到0.6的二进制是0.100110011001...循环节是1001。这是一个无限循环小数无法精确表示。这就是为什么在编程中浮点数运算会有精度问题。0.6在二进制中无法精确表示就像1/3在十进制中无法精确表示一样。注意事项涉及金额计算时不要用浮点数要用整数或定点数。这是无数血泪教训换来的经验。5.3 大数转换的实用策略当数字超过一个字节8位时手算容易出错。这时候可以用“分组转换”的策略先把大数按4位一组转成十六进制再把十六进制转成其他进制。比如217转化为二进制是11011001但如果是一个32位数比如3735928559直接转二进制太长。可以先转十六进制3735928559 0xDEADBEEF。然后每一位十六进制展开成4位二进制D1101E1110A1010D1101B1011E1110E1110F1111。拼起来就是32位二进制。这个方法的好处是十六进制和二进制之间的转换是机械的不需要计算只需要查表。而且十六进制表示比二进制短得多不容易看花眼。5.4 工具辅助与手动验证虽然手算能力很重要但实际工作中没必要什么都手算。计算器、编程语言、在线工具都可以用。关键是要有验证的意识。比如你用Python算了一个转换结果可以用另一种方法验证。bin(217)得到0b11011001你可以手动按权重展开验证128641681217一致。或者用hex(217)得到0xd9再int(d9,16)得到217一致。实操心得在嵌入式开发中我习惯用计算器的“程序员模式”来验证寄存器配置。Windows自带的计算器就有这个模式可以同时显示十六进制、十进制、八进制、二进制非常方便。输入一个值四种进制同时显示一眼就能看出位模式。6. 进制转换的进阶应用与扩展6.1 位运算与进制转换的结合位运算与、或、异或、取反、左移、右移是二进制层面的操作和进制转换密切相关。比如你想把一个寄存器的bit3置1可以用“或”运算reg | (1 3)。想把bit3清零可以用“与”运算reg ~(1 3)。想检查bit3是否为1可以用“与”运算if (reg (1 3))。这些操作在十六进制层面看就是修改某一位的值。比如0xE5的bit3是0置1后变成0xED。因为0xE511100101bit3是0置1后111011010xED。理解位运算和进制转换的关系能让你在配置寄存器、解析协议、优化代码时更加得心应手。6.2 字符编码中的进制转换ASCII码表是字符和数值的对应关系。比如‘A’是65十六进制是0x41二进制是01000001。‘a’是97十六进制是0x61二进制是01100001。‘0’是48十六进制是0x30二进制是00110000。在十六进制编辑器中查看文本文件时看到的就是这些编码值。比如“Hello”对应的十六进制是48 65 6C 6C 6F。如果你知道ASCII码表就能直接读出内容。UTF-8编码中中文字符通常占3个字节。比如“中”的UTF-8编码是E4 B8 AD。这些字节用十六进制表示转成二进制后可以看到UTF-8的编码规则1110xxxx 10xxxxxx 10xxxxxx。6.3 网络协议中的进制表示网络协议中的数据通常以十六进制表示。比如IP地址192.168.1.1每个字节用十进制表示但底层是二进制。MAC地址00:1A:2B:3C:4D:5E每个字节用十六进制表示。在分析网络数据包时你会看到大量的十六进制数据。理解进制转换能让你快速定位关键字段。比如TCP头部的源端口和目标端口各占2个字节用十六进制表示就是4位十六进制数。看到0x01BB就知道端口是443。6.4 进制转换在CTF比赛中的应用CTFCapture The Flag比赛中进制转换是基本功。逆向工程题目中经常需要把十六进制的机器码转成二进制分析指令。密码学题目中经常需要把十六进制的密文转成二进制进行异或运算。杂项题目中经常需要识别文件的十六进制魔数。比如“2025数证杯初赛wp 二进制”这个热词说明比赛中有一道二进制相关的题目。这类题目通常涉及二进制文件的逆向分析需要把十六进制的机器码转成汇编指令理解程序逻辑找到flag。实操心得打CTF时我习惯用Python的pwntools库来处理进制转换和二进制数据。p32()、p64()可以打包32位和64位整数u32()、u64()可以解包。这些函数在处理二进制数据时非常方便。进制转换这件事说到底就是“翻译”。二进制、八进制、十六进制、十进制都是描述同一个数值的不同语言。掌握它们之间的转换不是为了考试而是为了在需要的时候能快速理解数据的含义。我自己的经验是刚开始手算会慢但算多了之后看到十六进制就能反应出二进制位模式看到二进制就能估出十进制大小。这种直觉是靠反复练习积累出来的。