进制:从数苹果到互相转换
2021 年 6 月 15 日 · 2 分钟读完
工作里遇到要手动换算负数的情况,想做个记录。在讲负数之前,得先把进制和进制转换弄清楚。这一篇是「数字在计算机里」系列的第一篇。
四种常见进制
| 进制 | 英文缩写 | 用到的数字 | 规则 |
|---|---|---|---|
| 二进制 | BIN / B | 0、1 | 逢二进一 |
| 八进制 | OCT / O | 0 ~ 7 | 逢八进一 |
| 十进制 | DEC / D | 0 ~ 9 | 逢十进一 |
| 十六进制 | HEX / H | 0 ~ 9、A ~ F | 逢十六进一 |
拿十进制来说,9 + 1 个位满十归零,向十位进一,结果从一位数变成了两位数 10。其他进制完全一样,只是「满几」不同:
二进制: 1 + 1 = 10
八进制: 7 + 1 = 10
十六进制:9 + 1 = A,F + 1 = 10 (A~F 分别代表 10~15)
「10」不一定是十
每种进制加到最后都会出现 10,但它们代表的数量并不相同。假设一共有 16 个苹果:
十进制数: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
二进制数: 1, 10, 11, 100, 101, 110, 111, 1000, ..., 1111, 10000
八进制数: 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 20
十六进制数:1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10
16(D)、10000(B)、20(O)、10(H)都是 16 个。表示方法不同,数量相同。
偷懒的办法:系统计算器
只是想换算一下的话,Windows 自带的计算器就够了:搜索「计算器」打开,左上角菜单切到「程序员」模式。

HEX、DEC、OCT、BIN 四行里,点哪一行就用哪种进制输入,另外三行同步显示换算结果。比如在 DEC 下输入 16,会看到 HEX 10、OCT 20、BIN 0001 0000。

其他进制转十进制:按权展开
先看二进制里几个特殊的数:
二进制:0001 0010 0100 1000
十进制: 1 2 4 8
权值: 2^0 2^1 2^2 2^3
每一位上的 1 都代表 2 的某次方。所以 1111 = 2^3 + 2^2 + 2^1 + 2^0 = 8 + 4 + 2 + 1 = 15。
规则可以推广到任何进制:从右往左第 n 位上的数字 a,代表 a × 基数^(n-1),把每一位加起来就是十进制结果。
二进制 1111 0001 = 1×2^7 + 1×2^6 + 1×2^5 + 1×2^4 + 0×2^3 + 0×2^2 + 0×2^1 + 1×2^0 = 241
八进制 1234 5670 = 1×8^7 + 2×8^6 + 3×8^5 + 4×8^4 + 5×8^3 + 6×8^2 + 7×8^1 + 0×8^0 = 2739128
十六进制 123A BCDE = 1×16^7 + 2×16^6 + 3×16^5 + 10×16^4 + 11×16^3 + 12×16^2 + 13×16^1 + 14×16^0 = 305839326
带小数的也一样,小数点后面的指数从 -1 开始往下数:
二进制 1111.0101 = 2^3 + 2^2 + 2^1 + 2^0 + 0×2^-1 + 1×2^-2 + 0×2^-3 + 1×2^-4 = 15.3125
十进制转其他进制
整数:除基取余,倒着读
十进制 372 转二进制(除二取余):
372 ÷ 2 = 186 …… 0
186 ÷ 2 = 93 …… 0
93 ÷ 2 = 46 …… 1
46 ÷ 2 = 23 …… 0
23 ÷ 2 = 11 …… 1
11 ÷ 2 = 5 …… 1
5 ÷ 2 = 2 …… 1
2 ÷ 2 = 1 …… 0
1 ÷ 2 = 0 …… 1
从下往上读余数:1 0111 0100(B) = 372(D)
转八进制(除八取余):372 → 余 4,46 → 余 6,5 → 余 5,读作 564(O)
转十六进制(除十六取余):372 → 余 4,23 → 余 7,1 → 余 1,读作 174(H)
十六进制的余数可能大于 9,别忘了换成字母。比如 444:余数依次是 12(C)、11(B)、1,读作 1BC(H)。
小数:乘基取整,正着读
0.125 转二进制(乘二取整):
0.125 × 2 = 0.25 …… 取整 0
0.25 × 2 = 0.5 …… 取整 0
0.5 × 2 = 1.0 …… 取整 1,小数部分为 0,结束
从上往下读:0.001(B) = 0.125(D)
但很多小数永远乘不完,比如 0.1458 转二进制会得到 0.001001... 一直循环下去。存多少位取决于给这个数分配了多少空间,这也是浮点数有精度误差的根源,系列第三篇会细讲。
二进制和八、十六进制互转:分组
1111(B)等于 15,再加 1 就是 16,正好在十六进制里进一位。所以 4 位二进制正好对应 1 位十六进制;同理 3 位二进制对应 1 位八进制。
二进制 1100 1111 0101
笨办法:先转十进制 3317,再转十六进制 CF5
聪明办法:从右往左每 4 位一组 → 1100 | 1111 | 0101 → C F 5
二进制 110 011 110 101(每 3 位一组)→ 6 3 6 5(O)
整数部分从右往左分组,小数部分从左往右分组,不够的位补 0。
延伸
- 在代码里转换:C# 用
Convert.ToString(372, 2)得到"101110100",Convert.ToInt32("1BC", 16)得到 444;格式化十六进制可以写372.ToString("X")。C# 7 起还能直接写二进制字面量0b1_0111_0100和十六进制字面量0x174,下划线只是分隔符。 - 为什么程序员偏爱十六进制:一个字节正好 8 位,等于两位十六进制,看内存、看报文时一眼就能对上字节边界。PLC 地址、颜色值(
#FF8800)、MAC 地址都是这个原因。 - 八进制几乎只剩一个地方常见:Linux 的文件权限
chmod 755,每一位八进制正好对应 rwx 三个开关。
原文首发于 blog.csdn.net