进制转换——用不同的数字语言说话
中等5用不同进制表达数字——二进制、八进制、十进制、十六进制轻松学
你平时用的数字是十进制,从0到9。但计算机只懂二进制,只有0和1。就像同样一句话,可以用中文、英文、法文来说。不同进制就是不同数字语言。我们来学几种常见进制,学会了就能和计算机“说同一种话”了。
什么是进制?——每个进制有自己的“数字词典”
- 二进制:基数是2,用到的数字只有
0和1。计算机内部所有信息都用二进制存储。 - 八进制:基数是8,数字是
0~7。(注意:没有8和9) - 十进制:基数是10,数字是
0~9。我们日常用的就是它。 - 十六进制:基数是16,数字是
0~9,外加A~F。其中A代表10,B代表11……F代表15。比如十进制的15,转成十六进制就是F。
? 生活小例子:钟表上用的是六十进制(60秒=1分),而一周用的是七进制(7天=1周)。不同进制就像不同国家的语言,但数字本身的意思是一样的。
怎么把十进制数翻译成其他进制?——短除法倒着取余
方法:不断除以目标进制,记下每次的余数,最后把余数从下往上(也就是倒着)排列。
比如把十进制的 15 转成二进制:
- 15 ÷ 2 = 7 余 1
- 7 ÷ 2 = 3 余 1
- 3 ÷ 2 = 1 余 1
- 1 ÷ 2 = 0 余 1
倒着取余数:1111,所以十进制的15等于二进制的1111。
再转成八进制:
- 15 ÷ 8 = 1 余 7
- 1 ÷ 8 = 0 余 1
倒着取:17,所以八进制是17(读作“一七”,不是十七)。
转成十六进制:
- 15 ÷ 16 = 0 余 15,15对应
F,所以是F。
小窍门:用短除法时,当商变成0就停止。就像分零食:把一堆糖果按照每袋装几颗分好,剩下的就是余数。
怎么把其他进制数翻译成十进制?——按位权展开相加
每个数字所在的位置都有一个“位权”,从右往左第0位的位权是 进制^0=1,第1位是 进制^1,第2位是 进制^2……然后把每个数字乘以所在位的位权,再相加。
例如:二进制 1010 转十进制:
- 从右往左:第0位0×2⁰=0,第1位1×2¹=2,第2位0×2²=0,第3位1×2³=8
- 加起来:0+2+0+8=10,所以
1010₂ = 10₁₀。
再比如八进制 17 转十进制:
- 第0位7×8⁰=7,第1位1×8¹=8,总和=15。
十六进制 F 转十进制:F=15,第0位,所以就是15。
生活例子:就像算零花钱,5张1元(位权1)、3张10元(位权10),加起来就是5+30=35元。
为什么计算机用二进制,程序员爱用十六进制?
- 计算机用二进制:因为电路只有两种状态:开(1)和关(0),二进制最省事,不容易出错。
- 程序员用十六进制:因为十六进制可以把一长串二进制写成短的形式。每4位二进制正好对应1位十六进制。比如二进制
1111就是十六进制的F,二进制1010就是A。这样写起来既节省空间,又容易看出和二进制的关系。
C++ 自带“翻译机”——直接用库函数转换
C++ 中有现成的工具,我们可以像用翻译 App 一样简单转换。看下面代码:
#include <iostream>
#include <bitset> // 用于二进制输出
using namespace std;
int main() {
int n;
cout << "请输入一个十进制整数: ";
cin >> n;
// 输出二进制(用8位表示)
cout << "二进制: " << bitset<8>(n) << endl;
// 输出八进制(加上前缀0表示八进制)
cout << "八进制: " << oct << n << "(前缀0) " << dec << endl;
// 输出十六进制(加上前缀0x表示十六进制)
cout << "十六进制: " << hex << n << "(前缀0x) " << dec << endl;
return 0;
}
运行一下:输入15,输出:
- 二进制:
00001111 - 八进制:
17(前面会自动加前缀0表示八进制数,如017) - 十六进制:
f(前面有0x表示十六进制,如0xf)
注意:
bitset<8>中的8表示用8位二进制显示,不足的左边补0。如果想显示更多位,可以改成bitset<16>。oct和hex是输入输出修饰符,用来告诉 cout 按八进制或十六进制输出;后面的dec是改回十进制,不然之后的所有数字都会按八进制输出。
自己动手写一个“手工转换机”——十进制转二进制(循环除2取余)
用库函数很方便,但自己实现更能理解原理。下面代码手动将十进制转成二进制(字符串形式):
#include <iostream>
#include <string> // 使用字符串
using namespace std;
int main() {
int n; // 输入的十进制数
cout << "请输入一个十进制整数: ";
cin >> n;
string result = ""; // 用来存放二进制结果(字符串)
int temp = n; // 临时变量,避免改变原值
while (temp > 0) {
// 取余:余数就是当前最低位的二进制位
int remainder = temp % 2; // 余数只能是0或1
// 把余数转成字符('0'或'1')拼接到结果前面(因为要倒序)
result = char('0' + remainder) + result;
temp = temp / 2; // 继续处理商
}
// 如果输入0,结果应该是"0"
if (result == "") result = "0";
cout << "二进制: " << result << endl;
return 0;
}
这段代码用 while 循环反复除2取余,并把余数放到字符串的最前面,这样最后得到的就是正确的二进制(不需要手动倒序)。
试试看:输入
15,输出1111;输入0,输出0。(注意:代码里单独处理了输入0的情况,否则while循环不执行,result为空字符串。)
? 完整可运行示例——一个简单的进制转换器
下面程序让用户输入一个十进制数,然后同时输出二进制、八进制、十六进制(包含库函数和自实现二进制):
#include <iostream>
#include <bitset> // 库函数二进制输出
#include <string> // 手动转换需要字符串
using namespace std;
int main() {
int num; // 用户输入的十进制数
cout << "请输入一个十进制整数: ";
cin >> num;
// ---------- 库函数方式 ----------
cout << "\n【使用库函数】" << endl;
cout << "二进制(8位): " << bitset<8>(num) << endl;
cout << "八进制: " << oct << num << "(前缀0) " << dec << endl;
cout << "十六进制: " << hex << num << "(前缀0x) " << dec << endl;
// ---------- 手动实现二进制 ----------
string bin = ""; // 手动计算的二进制结果
int temp = num; // 临时变量
if (temp == 0) {
bin = "0"; // 输入0的特殊处理
} else {
while (temp > 0) {
int digit = temp % 2; // 当前位(0或1)
bin = char('0' + digit) + bin; // 拼到前面
temp /= 2; // 去掉最低位
}
}
cout << "手动计算的二进制: " << bin << endl;
return 0;
}
如果输入 15,输出效果如下:
请输入一个十进制整数: 15
【使用库函数】
二进制(8位): 00001111
八进制: 17(前缀0)
十六进制: f(前缀0x)
手动计算的二进制: 1111
注意:手动计算的二进制没有前面的0,所以显示为
1111,而库函数bitset<8>补足了8位变成00001111。
? 新手最容易犯的3个错误
-
余数顺序搞反
比如转二进制时,把第一个余数放最前面,结果变成1111→1111(正确)或者把第一个余数放最后,得到1111→1111?不,如果顺序反了,15÷2余1→7÷2余1→3÷2余1→1÷2余1,如果按顺序正着写就是1111,实际上和倒序一样(巧合)。但换成其他数比如十进制9:9÷2余1→4÷2余0→2÷2余0→1÷2余1,正着写1001,而正确是倒序得到1001,呃,其实还是对的?注意:这个例子正序和倒序不同!9÷2第一次余1,最后余1,中间两次余0,如果正着写(从第一次余数到最后一次余数)是1001,而正确的倒序(从最后一次余数到第一次余数)也是1001,因为对称。但换一个不对称的数:10(十进制):10÷2余0→5÷2余1→2÷2余0→1÷2余1,正序得到0101(即101),而正确倒序是1010(即1010)。明显不同!所以一定要把余数从后往前写。 -
十六进制中字母大小写
C++中输出十六进制时,字母默认是小写(af),但也可以改成大写:用15对应A~F。cout << uppercase << hex << num;。手写转换时,注意10 -
忘记在C++中切换回十进制
用oct或hex后,如果不加dec恢复,后面所有整数都会按八进制或十六进制输出。例如:cout << hex << 15 << " " << 16; // 输出 f 10,因为16在十六进制是10而加上
dec后,cout << hex << 15 << dec << " " << 16;输出f 16。
? 学完这个,接下来可以学什么?
- 进制之间的快速转换:比如二进制 ↔ 十六进制,每4位二进制一组直接转成一位十六进制。
- 位运算:在C++中使用
&(与)、|(或)、^(异或)、<<(左移)、>>(右移)对二进制位进行操作,很多算法题会用到。 - 大数的进制转换:当十进制数很大(超过int范围)时,需要用字符串模拟除法,这在信息学竞赛中很常见。
进制转换是计算机世界的“通用语言”,掌握它,你就更懂计算机的底层逻辑了!
例题精讲
将二进制数101101.01转换为十进制数,结果正确的是?
十六进制数0x1F3转换为十进制数是499。
以下C++函数将十进制正整数转换为二进制字符串(无前导零)。请填空。
string decToBin(int n) {
if (n == 0) return "0";
string s = "";
while (n > 0) {
s = char('0' + n % 2) + s;
___;
}
return s;
}八进制数73.4转换为十六进制数,结果最接近以下哪个?
在C++中,使用std::cout << std::oct << 255 将输出377。(假设已经包含<iomanip>)