第21章 计算机的数制

第21章 计算机的数制

GESP 三级定位
等级知识块考查频率
GESP C++ 三级进制转换(二 / 八 / 十 / 十六)⭐⭐⭐

数制(计数制)是用一组固定符号和统一规则表示数值的方法。计算机底层用二进制存储与运算;为了方便书写与阅读,又常用八进制、十六进制;而人类最熟悉的是十进制。本章讲清四种进制的基数、位权,以及它们之间的相互转换。

21.1 数制的基本概念

21.1.1 基数

基数 = 每个数位上可用的符号个数。

  • 十进制:基数 10,符号 0~9
  • 二进制:基数 2,符号 0、1
  • 八进制:基数 8,符号 0~7
  • 十六进制:基数 16,符号 0~9、A~F(A=10,B=11,…,F=15)

21.1.2 位权

位权 = 基数的 nn 次方,从右往左、下标从 0 开始。

十进制 123:

1×102+2×101+3×100=1231 \times 10^2 + 2 \times 10^1 + 3 \times 10^0 = 123

位权示意:数字 4567

21.2 计算机中常用的数制

21.2.1 十进制(Decimal)

后缀 D(可省略);逢十进一、借一当十,日常生活使用。

21.2.2 二进制(Binary)

后缀 B;仅 0、1;逢二进一。是计算机唯一的底层存储格式(晶体管导通/截止对应 1/0)。

  • 加法:0+0=0, 0+1=1, 1+0=1, 1+1=100+0=0,\ 0+1=1,\ 1+0=1,\ 1+1=10
  • 减法:0−0=0, 1−0=1, 1−1=0, 10−1=10-0=0,\ 1-0=1,\ 1-1=0,\ 10-1=1

21.2.3 八进制(Octal)

后缀 O 或 Q;3 位二进制 = 1 位八进制,用来简化长二进制串的书写。

21.2.4 十六进制(Hexadecimal)

后缀 H;4 位二进制 = 1 位十六进制,编程中最常用(内存地址、颜色值、位运算掩码等),逢十六进一。

为什么程序员爱用十六进制?

一个字节(8 位)用二进制要写 8 个数字,用十六进制只需 2 个(00~FF),既短又好和二进制互转(每 4 位一组)。例如内存地址 0x1A2B 比 0001101000101011 好读得多。

21.3 数制之间的转换

21.3.1 任意进制 → 十进制

规则:按位权展开求和。

  1. 二进制 1011B1011\text{B}: 1×23+0×22+1×21+1×20=111 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 1 \times 2^0 = 11
  2. 八进制 123O123\text{O}: 1×82+2×81+3×80=831 \times 8^2 + 2 \times 8^1 + 3 \times 8^0 = 83
  3. 十六进制 1A3H1\text{A}3\text{H}: 1×162+10×161+3×160=4191 \times 16^2 + 10 \times 16^1 + 3 \times 16^0 = 419

21.3.2 十进制 → 任意进制

  • 整数部分:除基取余,逆序输出
  • 小数部分:乘基取整,顺序输出(三级一般只考整数)

示例1:十进制 11 → 二进制

11 ÷ 2 = 5 余 1
5 ÷ 2 = 2 余 1
2 ÷ 2 = 1 余 0
1 ÷ 2 = 0 余 1
余数逆序:1011

示例2:十进制 83 → 八进制

83 ÷ 8 = 10 余 3
10 ÷ 8 = 1 余 2
1 ÷ 8 = 0 余 1
逆序得:123

示例3:十进制 419 → 十六进制

419 ÷ 16 = 26 余 3
26 ÷ 16 = 1 余 10(A)
1 ÷ 16 = 0 余 1
逆序得:1A3

21.3.3 二进制 ↔ 八 / 十六进制

  • 二进制 → 八进制:从右往左每 3 位一组,不足左补 0。 例:101101B101101\text{B} → 101 101 → 55O55\text{O}
  • 二进制 → 十六进制:每 4 位一组,不足左补 0。 例:1011010110110101 → 1011 0101 → B5H\text{B}5\text{H}
  • 反过来:八/十六进制转二进制,就是 1 位拆成 3 位 / 4 位,去掉前导 0。
分组方向别搞反

分组必须从右往左(低位开始)每 3/4 位一组,左边不足补 0。写成 010 110 101 这种从左补 0 是错误的,要从右补。例如 101101 应分 101 101 不是 101 10 1。

21.4 C++ 进制与转换示例

C++ 直接支持多种进制字面量,并可用 <bitset> 输出二进制、<iomanip> 控制输出进制。

base_demo.cpp
#include <iostream>
#include <bitset> // 用于二进制输出
#include <iomanip> // 用于 hex / oct 输出
using namespace std;

// 十进制整数转二进制字符串(除 2 取余)
void decToBin(int n) {
if (n == 0) { cout << 0; return; }
int bits[32], k = 0;
int x = n;
while (x > 0) { bits[k++] = x % 2; x /= 2; }
for (int i = k - 1; i >= 0; i--) cout << bits[i];
}

int main() {
int x = 255;
cout << "十进制 " << x << " 的二进制: "
<< bitset<8>(x) << endl; // 11111111

// 字面量与不同进制输出
int a = 0xFF; // 十六进制字面量
int b = 0177; // 八进制字面量(以 0 开头)
cout << "0xFF = " << a << " , 0177 = " << b << endl;

cout << "255 八进制 = " << oct << x << endl; // 377
cout << "255 十六进制 = " << hex << x << endl; // ff
return 0;
}
运行结果

bitset<8>(255) 输出 11111111;0xFF 即 255,0177 即 127;oct 输出 377,hex 输出 ff。可见 C++ 里进制只是「书写/显示」的差异,底层一律二进制存。

21.5 选择题练习

1. 十六进制数 1A 转换为十进制是?

A. 26
B. 16
C. 10
D. 25

点击展开参考答案与解析

答案:A

解析:1A16=1×16+10=261\text{A}_{16} = 1 \times 16 + 10 = 26,选 A。

2. 将十进制数 100 转换为二进制,结果是?

A. 1100100
B. 1101000
C. 1011100
D. 1110000

点击展开参考答案与解析

答案:A

解析:100 除 2:100→50余0, 50→25余0, 25→12余1, 12→6余0, 6→3余0, 3→1余1, 1→0余1;逆序 1100100,选 A。

3. 二进制数 111010 转换为八进制,结果是?

A. 72
B. 73
C. 71
D. 36

点击展开参考答案与解析

答案:A

解析:111010 从右 3 位分组:111 010 → 7 2 = 72,选 A。

4. 关于二进制与十六进制的转换,下列说法正确的是?

A. 每 3 位二进制对应 1 位十六进制
B. 每 4 位二进制对应 1 位十六进制
C. 每 2 位二进制对应 1 位十六进制
D. 二进制与十六进制无法快速互转

点击展开参考答案与解析

答案:B

解析:4 位二进制 = 1 位十六进制,选 B(3 位对应的是八进制)。

5. C++ 中,八进制字面量的特征是?

A. 以 0x 开头
B. 以 0 开头
C. 以 0b 开头
D. 以 H 结尾

点击展开参考答案与解析

答案:B

解析:C++ 八进制字面量以数字 0 开头(如 0177),0x 是十六进制,0b 是二进制(C++14 起),选 B。

SShowball OI知识手册