news 2026/10/1 21:44:27

数制转换全解析:二进制、八进制、十进制与十六进制实战避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数制转换全解析:二进制、八进制、十进制与十六进制实战避坑

1. 为什么值得花时间把数制转换彻底搞明白

刚入行那几年,我一直觉得数制转换是学校里应付考试的东西,工作中用到再查一下就行。直到有次调试一个传感器驱动,数据手册上写着寄存器地址0x4002 3800,偏移量0x1C,而我在代码里用十进制写偏移量,怎么算都不对,白白折腾了一下午。那次之后我才真正把二进制、八进制、十进制、十六进制这套东西系统梳理了一遍。

数制本质上就是同一堆数量的不同表达方式。十进制之所以成为日常默认,是因为人有十根手指;计算机用二进制,是因为电路只有通和断两种稳定状态;八进制和十六进制被发明出来,纯粹是因为二进制写起来太长,人眼扫过去容易数错。理解这一点,后面的转换就不再是死记硬背,而是顺理成章的换算。

这篇文章主要面向三类人:一是刚接触编程或者嵌入式的新手,看到0x、0b就发怵;二是做网络、运维、逆向的朋友,经常要在不同进制之间来回跳;三是准备考试或者面试,需要把转换过程讲清楚的人。我会把原理、手算方法、代码实现、常见坑都过一遍,尽量做到看完就能上手。文中涉及参数和步骤的地方,我会把推导过程写出来,而不是只丢一个结论。

2. 数制的本质:位权、基数与表示法

2.1 位权到底是什么,一个生活化的类比

先说一个最核心的概念:位权。你手里有一叠钱,面额分别是 100、10、1,那数字 345 就表示 3 张 100、4 张 10、5 张 1,加起来 345。这里的 100、10、1 就是位权,而 10 是基数,因为每往左一位,代表的量就乘以 10。

计算机的世界里,基数变成了 2。二进制数字 1011,从右往左的位权依次是 1、2、4、8,所以它等于 1×1 + 1×2 + 0×4 + 1×8 = 11。这个"乘基数、加结果"的动作,就是所有进制转十进制的基本方法,没有例外。

把这个思路推广开:

  • 八进制基数 8,位权是 8 的幂:1、8、64、512……
  • 十进制基数 10,位权是 10 的幂:1、10、100、1000……
  • 十六进制基数 16,位权是 16 的幂:1、16、256、4096……

提示:位权是理解一切进制转换的钥匙。凡是搞不清某个数怎么来的,先把它每一位的位权列出来,问题基本就迎刃而解。

2.2 基数决定了几套符号够用

基数决定了这个进制需要多少个不同的数字符号。十进制需要 0 到 9 共十个符号,够用。二进制只要 0 和 1 两个。八进制要 0 到 7 八个。十六进制最特殊,需要十六个符号,可阿拉伯数字只有 0 到 9 十个,怎么办?于是借用了字母 A 到 F,分别代表 10、11、12、13、14、15。

这也是为什么你在代码里经常看到0xFF这种写法,F 就是 15,两个 F 拼起来就是 255。刚接触的人容易卡在"A 为什么等于 10",其实没有为什么,就是约定,就跟扑克牌里 J 代表 11 一样,用起来方便而已。

不同语言和工具对进制的书写约定大同小异,下面这张表建议存一下:

进制常见前缀示例典型场景
二进制0b0b1010位运算、掩码、寄存器标志位
八进制0或0o0o17或017Linux 文件权限、早期 C 代码
十进制无255日常计算、业务逻辑
十六进制0x0xFF内存地址、颜色值、字节流

需要特别留个心眼的是八进制。C 语言里以0开头的数字会被当成八进制,所以int x = 010;里 x 实际是 8,不是 10。这个坑我踩过,当时排查一个数组下标越界,最后发现是某个常量前面手滑多了个零。

2.3 十六进制为什么和二进制是"亲兄弟"

十六进制在计算机领域地位特殊,原因就一个:16 是 2 的 4 次方。这意味着每一个十六进制位,刚好对应四个二进制位,不多不少。

具体对应关系是固定的,背下来收益极高:

十六进制二进制十六进制二进制
0000081000
1000191001
20010A1010
30011B1011
40100C1100
50101D1101
60110E1110
70111F1111

有了这张表,二进制和十六进制之间的转换就变成了"四换一、一拆四"的拼图游戏,完全不需要做乘法和除法。比如1101 1010,直接对着表拆成D和A,结果就是0xDA。反过来0x3F7,拆成3F7,各自展开成0011 1111 0111就行了。

八进制同理,只不过它是 2 的 3 次方,所以是"三位一组"。这也是为什么八进制在现代编程里用得越来越少——四位一组比三位一组更贴合字节的边界(一个字节 8 位,刚好两个十六进制位)。

3. 四类进制的核心转换方法全拆解

3.1 任意进制转十进制:按位权展开求和

这是最基础也最通用的方法。把每一位数字乘以它对应的位权,然后全部加起来。

以二进制11010为例,从右往左标位权:

位数: 1 1 0 1 0 位权: 16 8 4 2 1 计算: 1×16 + 1×8 + 0×4 + 1×2 + 0×1 = 16 + 8 + 2 = 26

八进制237转十进制:

7×1 + 3×8 + 2×64 = 7 + 24 + 128 = 159

十六进制2AF转十进制,注意 A=10、F=15:

F×1 + A×16 + 2×256 = 15 + 160 + 512 = 687

这套方法对小数部分同样适用,只不过位权变成负幂次。比如二进制0.101:

1×2⁻¹ + 0×2⁻² + 1×2⁻³ = 0.5 + 0 + 0.125 = 0.625

注意:手算时遇到很长的数,建议从右往左数,把位权写在数字上方,这样不容易错位。错位是手算最常见的失误,一旦某一位偏了,后面全错。

3.2 十进制转其他进制:整数除基取余,小数乘基取整

整数部分用除基取余、逆序排列。以十进制 156 转二进制为例:

156 ÷ 2 = 78 ... 余 0 ← 最低位 78 ÷ 2 = 39 ... 余 0 39 ÷ 2 = 19 ... 余 1 19 ÷ 2 = 9 ... 余 1 9 ÷ 2 = 4 ... 余 1 4 ÷ 2 = 2 ... 余 0 2 ÷ 2 = 1 ... 余 0 1 ÷ 2 = 0 ... 余 1 ← 最高位

把余数从下往上读:10011100。验证一下:128+16+8+4=156,对的。

转八进制和十六进制思路完全一样,只是除数换成 8 和 16。156 转十六进制:

156 ÷ 16 = 9 ... 余 12(C) 9 ÷ 16 = 0 ... 余 9

逆序读是9C,验证:9×16+12=156。

小数部分则相反,用乘基取整、顺序排列。以十进制 0.6875 转二进制为例:

0.6875 × 2 = 1.375 → 取整 1,保留 0.375 0.375 × 2 = 0.75 → 取整 0,保留 0.75 0.75 × 2 = 1.5 → 取整 1,保留 0.5 0.5 × 2 = 1.0 → 取整 1,保留 0

取整结果按顺序读:0.1011。验证:0.5+0.125+0.0625=0.6875,吻合。

这里就要说到那个热搜问题了:十进制小数转换为二进制有精度限制时需要考虑舍入吗?答案是必须考虑,而且这是很多人踩过的真实坑。因为二进制只能精确表示那些分母是 2 的幂次的分数,像 0.1、0.2、0.3 这种十进制小数,转成二进制是无限循环的。用有限位数表示就必然要截断或者舍入。

举个实际例子,很多语言里0.1 + 0.2 != 0.3,就是因为这个。如果你在做金额计算、科学计算这类对精度敏感的场景,别用浮点数,改用整数(以分为单位)或者专门的十进制库(比如 Python 的decimal、Java 的BigDecimal)。至于舍入方式,常见的有四舍五入、银行家舍入(round half to even)、向上/向下取整,金融场景优先考虑银行家舍入,能减少系统性偏差。

3.3 二进制与八进制、十六进制的快捷转换

前面说过,十六进制一位对四位,八进制一位对三位。利用这个特性可以跳过十进制直接互转,速度飞快。

二进制转十六进制:从小数点开始,往左往右各四位一组,不足补零。

二进制: 101 1010 1111 分组: 0101 1010 1111 (最左边不足四位,补个零) 结果: 5 A F → 0x5AF

二进制转八进制:同样分组,但是三位一组。

二进制: 101101011 分组: 101 101 011 (从右往左三位一组) 结果: 5 5 3 → 0o553

提示:最左边和最右边不足位时补零,补的是数值位方向的零,不要补错位置。左边补零不改变数值,右边补零会改变数值,所以小数部分右侧补零要慎重——实际上转换时小数部分是从左往右分组,不足的在最右补零,这是为了凑齐分组,数值上是等价的。

3.4 负数与补码:绕不开的一道坎

热搜里"负数的二进制""二进制补码"出现频率很高,说明这是大家的痛点。计算机里表示负数,主流方案是补码。

以 8 位为例,正数 5 是0000 0101。要得到 -5,步骤是:先取反得到1111 1010,再加 1 得到1111 1011。这个1111 1011就是 -5 的补码表示。

为什么要这么麻烦?因为用补码可以让减法和加法共用一套电路。5 + (-5)用补码算:

0000 0101 + 1111 1011 ----------- 1 0000 0000 ← 最高位的进位溢出丢弃

结果是 0,完美。如果不用补码用原码,减法电路和加法电路就得分开设计,硬件成本高得多。

补码还有个好处是 0 只有一种表示,而原码和反码里 +0 和 -0 是两种,判断起来麻烦。

实操中要注意的是溢出。8 位有符号数范围是 -128 到 127,129 就溢出了。当你看到1000 0000这个值,如果是无符号就是 128,有符号就是 -128,临界点要格外小心。

4. 代码和工具里的数制转换实操

4.1 用 Python 和 C 快速验证转换结果

Python 内置了转换函数,调试时非常方便:

# 十进制转其他进制 print(bin(156)) # 0b10011100 print(oct(156)) # 0o234 print(hex(156)) # 0x9c # 其他进制转十进制 print(int('10011100', 2)) # 156 print(int('234', 8)) # 156 print(int('9C', 16)) # 156 # 处理小数 from decimal import Decimal, getcontext getcontext().prec = 30 print(Decimal(0.1)) # 展示浮点数的真实存储值

C 语言里,printf的格式说明符可以直接输出不同进制:

#include <stdio.h> int main() { int n = 156; printf("十进制: %d\n", n); // 156 printf("八进制: %o\n", n); // 234 printf("十六进制: %x\n", n); // 9c printf("十六进制大写: %X\n", n); // 9C return 0; }

这里有个细节:printf没有二进制格式符,因为 C 标准没纳入。要输出二进制得自己写循环或者用非标准扩展。另外%o输出八进制时前面不会自动加0,%#o才会加,%#x会加0x。

注意:C 里scanf读十六进制用%x,但如果输入超过int范围,结果未定义。处理大数要用strtoul之类的函数,并检查errno。

4.2 十六进制编辑器和二进制分析场景

做逆向或者排查文件格式问题时,十六进制编辑器是必备工具。像 HxD 这类工具,打开任意文件都能看到每个字节的十六进制值,右侧配上对应的 ASCII 字符显示。

举个例子,PNG 文件开头固定是89 50 4E 47 0D 0A 1A 0A。其中50 4E 47对应 ASCII 的 "PNG",89是高位字节,用来检测传输过程有没有被错误处理成文本模式。看懂这些,你就能快速判断一个文件是不是伪装了扩展名。

CTF 里常见的二进制题目,比如栈溢出、rip控制这类,本质也是要计算出精确的偏移量和地址。这些地址在反汇编器里都是十六进制,你要能快速把十六进制地址和内存布局对应起来。字节序(大端小端)也是这里的关键,0x12345678在小端机器上内存里是78 56 34 12,顺序反的。

4.3 数据库和其他工具中的进制玩法

通达信这类软件里,十六进制代码有时会出现在数据文件或者公式编码里。处理这类数据时,关键是把十六进制字节流正确地解码成有意义的数值或字符串,注意编码和字节序。

容器运维场景里也会遇到二进制相关的东西,比如某些组件的二进制分发包部署,用 systemd 管理时监听本地 socket 文件。这些路径配置在服务单元里通常以绝对路径给出,排查连接问题时要确认进程实际监听的路径和权限是否符合预期。

颜色领域更是十六进制的天下。网页和设计工具里#RRGGBB是标配,前两位是红、中间两位是绿、后两位是蓝,每个通道 0 到 255。像陶土白这种色号,查出来的 hex 值就是设计师和前端之间交接的通用语言。理解十六进制的位权,你就能心算出不同颜色值的亮度大概在什么区间。

5. 常见问题速查与避坑经验

5.1 数制转换常见问题排查表

实际工作中遇到的问题,很多是细节没处理干净。我把最常见的几类整理成表,方便对照:

问题现象可能原因排查方法解决方法
数值大了一倍误把八进制当十进制检查前缀是否有前导 0去掉前导零或改成十进制
负数结果异常忽略了补码表示确认是有符号还是无符号明确类型和位宽
小数转换不精确二进制无法精确表示用高精度库观察真实值改用整数或十进制库
十六进制地址算错位权错位或字节序搞反逐位列出位权重新算确认大小端,重新分组
颜色值对不上遗漏 # 或长度不对检查是否为 6 位完整格式补齐六位,区分大小写

5.2 手算提速的几个实用技巧

第一个技巧是先转十六进制再转二进制。比如要算十进制 5000 的二进制,直接除 2 要算十几次,但如果先算出十六进制1388,再一位拆四位,快得多,也不容易错。

第二个技巧是记住几个常用位权值。二的 1 到 16 次方背下来,转换时可以直接套:2、4、8、16、32、64、128、256、512、1024、2048、4096、8192、16384、32768、65536。这几个数在编程里出现频率极高,尤其 1024、65536 这类,看到就条件反射。

第三个技巧是善用分组。超过 10 位的二进制数,用人眼直接读很容易数错,从右往左每四位加个空格或者分隔符,瞬间清晰。很多编辑器和终端也支持高亮显示分组,用起来很顺手。

5.3 那些文档里不会写的坑

坑一:八进制的权限表示。Linux 里chmod 755里的 755 是八进制,7 表示读+写+执行(4+2+1),5 表示读+执行(4+1)。如果你用十进制思维理解 755,算出来完全不对。这种场景下,理解数制不是学术问题,是直接关系到权限是否配置正确。

坑二:浮点比较别用等号。前面说过 0.1 的二进制表示有误差,所以0.1 + 0.2 == 0.3在某些语言里返回 false。正确做法是比较绝对差值是否小于一个极小的阈值,比如abs(a - b) < 1e-9。金融计算则干脆不要用浮点。

坑三:位运算的符号扩展。对负数做移位或者与运算时,有符号数的符号位会扩展。比如-1 >> 1在很多语言里还是 -1,而不是一个大正数。做位掩码时,优先用无符号类型,避免符号位捣乱。

坑四:字符串和二进制数据的边界。像 C 里的strstr()这类字符串函数是用来处理以\0结尾的文本的,中间一旦出现\0就会提前截断。二进制内存里随时可能包含\0,所以查找二进制数据要用memmem或者带长度的比较函数,不能直接套字符串函数。这个坑在做协议解析时特别容易翻车。

坑五:字节序的隐蔽性。网络协议规定用大端,x86 是小端。当你手工拼接多字节数值时,如果不做转换,得到的会是反的。十六进制看起来都是一样的字符,但在内存里的排列顺序才是真相。

6. 硬件与进阶场景里的数制应用

6.1 键盘扫描与编码中的十六进制

用 Verilog HDL 设计一个十六进制键盘的扫描和编码电路,这个场景把数制用到了硬件层面。矩阵键盘通常是 4 行 4 列,扫描时逐行拉低,读列线状态,判断哪个键被按下。

十六进制键盘有 16 个键,从 0 到 F,每个键对应一个唯一的四位二进制编码。比如按下 "A",编码器输出1010。这个输出可以直接用于后续的显示驱动或者数据总线。

设计要点在于消抖。机械按键按下和释放时会有几十毫秒的抖动,扫描电路需要用计数器做延迟确认,或者用移位寄存器做状态过滤。如果扫描频率太高又没消抖,一个按键会被识别成多次,这是新手常见的问题。

另外编码器的优先级也要考虑。如果多个键同时按下,得有明确的优先级规则,通常按矩阵位置(低位优先或者高位优先)来确定输出。这是组合逻辑设计中容易忽略的细节。

6.2 从数制角度看数据存储与传输

磁盘、内存、网络,底层都是字节流。理解数制让你能"看见"这些字节。比如一个 32 位整数0x01020304,在内存里按小端存储是04 03 02 01。你在十六进制编辑器里看到的就是这个顺序。

网络抓包时,协议头的字段长度、标志位都定义到比特级别。TCP 头里那些标志位(SYN、ACK、FIN)各占一位,本质上是同一个字节里不同位置上的二进制位。理解位权,你就能自己算出标志位的组合值,也能从十六进制值反推出哪些标志位被置位了。

机器学习和人工智能领域也离不开数制。模型权重常见的是 FP16、BF16 这类浮点格式,它们的指数位和尾数位分配不一样,直接影响到模型的精度和显存占用。BF16 指数位和 FP32 一样是 8 位,尾数只留 7 位,牺牲精度换范围;FP16 指数 5 位、尾数 10 位,范围小但精度高一些。选择哪种格式,本身就是数字表示原理在实际工程里的取舍。

7. 写在最后的一点个人体会

数制转换这东西,看起来简单,但要真正用得顺,靠的是反复练和踩坑。我的建议是不要只背结论,而是每次遇到一个进制问题,都花三十秒在心里过一遍位权,时间长了就成了本能反应。

具体练习方式上,可以每天随手拿几个数做转换,比如看看时间戳的十六进制,看看文件大小的二进制,坚持一两周,基本就刻进肌肉记忆了。工具方面,手头常备一个十六进制编辑器和一个带多进制显示的计算器,遇到不确定的立刻验证,别靠猜。

另外提醒一句,涉及金额、坐标、传感器读数这类场景,一定要在动手前想清楚用什么数据类型和精度。数制选择错一次,排查成本可能远超预期。这是我最想传达的一条经验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 21:43:52

PicoVNA-R:USB矢量网络分析仪的射频测试新选择

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 21:41:15

航拍语义分割毕设实战:DeepLabv3+多骨干代码包与避坑指南

简介&#xff1a;这份资源是面向高校计算机、人工智能及相关专业学生的毕业设计参考项目&#xff0c;围绕DeepLabv3模型展开高分辨率航拍图像的语义分割实践&#xff0c;适合具备一定Python与深度学习基础、需要完成遥感或航拍场景分割课题的读者。压缩包共184个文件&#xff0…

作者头像 李华
网站建设 2026/10/1 21:40:15

做AI短剧的工具有哪些?按环节拆分工具链与提示词准备方法

做AI短剧的工具不是某一款软件&#xff0c;而是一条按环节衔接的工具链&#xff1a;剧本生成、角色与场景设定、分镜规划、图像或视频提示词准备、视频生成、配音剪辑。对于已有小说或剧本底稿、希望控制画面质量的创作者&#xff0c;提示词准备是决定外部生成模型效果上限的关…

作者头像 李华
网站建设 2026/10/1 21:40:06

百度OCR与PaddleOCR选型避坑指南:API调用、国产系统适配与生产容错

1. 这不是“调个API就完事”的活儿&#xff1a;为什么百度OCR入坑指南必须从底层逻辑讲起你搜“百度OCR文字识别”&#xff0c;首页弹出来的大多是“三行代码搞定身份证识别”“5分钟接入百度AI平台”。我试过——真信了&#xff0c;结果在客户现场调试到凌晨两点&#xff0c;发…

作者头像 李华
网站建设 2026/10/1 21:39:39

K9s 命令模式与导航模式解析:从 v0.1.2 交互重构到现代版本演进

云原生容器编排CLI运维 【免费下载链接】k9s &#x1f436; Kubernetes CLI To Manage Your Clusters In Style! 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/k9s/k9s 点击查看 免费下载 K9s 是用于管理 Kubernetes 集群的终端 UI 工具&#xff0c;其核心交互建…

作者头像 李华