进制的本质
进制(或基数)是表示数值的方法,它决定了数位的权重和数位的可能值。进制是基于一个固定的数(称为基数或进位基数)来构建的,每个数位上的数字乘以基数的相应幂次,然后将这些乘积相加得到该数的值。
常见进制
十进制:基数为10,是最常用的进制,也是人类日常生活中使用的进制。在十进制中,每个数位的值可以是0到9中的任意一个数字。
二进制:基数为2,是计算机科学中最基本的进制。在二进制中,每个数位的值只能是0或1。
八进制:基数为8,是一种较少使用的进制,但在某些编程语言中用于简化二进制数的表示。
十六进制:基数为16,是一种常用的进制,特别是在计算机编程中。在十六进制中,每个数位的值可以是0到9中的任意一个数字,以及A到F(或小写a到f)中的任意一个字母,分别代表10到15。
进制在计算机中的应用
在计算机科学中,进制转换非常重要,因为计算机内部使用二进制来表示和处理数据。计算机使用二进制是因为它易于通过电子电路实现,且具有较高的可靠性。十六进制和八进制通常用于简化二进制数的表示,因为它们可以更紧凑地表示相同数量的信息。
将任意进制转换为十进制
在任意进制中,每个数位上的数字乘以该位的权重(基数的幂次),然后将这些乘积相加得到该数的值。例如,二进制数 1011
可以表示为 1×2^3+0×2^2+1×2^1+1×2^0。
以通过遍历数位并计算每个数位的贡献来实现转换:对于数位 a[i]
,其贡献为 a[i] * (base^i).
其中 base
是进制的基数,i
是当前数位的索引(从0开始)
将十进制转换为任意进制
确定进制基数:首先确定目标进制的基数,例如二进制的基数是2,八进制的基数是8,十六进制的基数是16。
2.除基取余:将十进制数除以目标进制的基数,记录余数。然后,将商继续除以基数,重复这个过程,直到商为零。
3.余数逆序排列:将记录的余数逆序排列,得到目标进制的表示。
具体公式如下:
设 𝑛 为十进制数,𝑏为目标进制的基数,为每次除法操作的余数,
为每次除法操作的商。则转换过程可以表示为:
其中, 是最后一次除法操作的余数,也是目标进制表示的最低位。
最终,目标进制的表示为。
例如,将十进制数 10 转换为二进制:
因此,十进制数 10 的二进制表示为 1010。
例题
1.蓝桥2489进制
请问十六进制数 2021ABCD 对应的十进制是多少?
#include <iostream>
#include<string>
using namespace std;
int turn(char x){
if(x>='0'&&x<='9'){
return x-'0';
}else if(x>='A'&&x<='F'){
return x-'A'+10;
}else{
return -1;
}
}
int main()
{
string str="2021ABCD";
int count=0;
for(int i=0;i<8;i++){
//cout<<str[i];
char x=str[i];
int y=turn(x);
count=count*16+y;
}
cout<<count<<endl;
return 0;
}
或者直接用c++的十六进制表示法将0x2021ABCD赋值给一个unsigned int 数字
(在大多数现代系统上,unsigned int
通常是32位的,这意味着它可以表示的最大值是 0xFFFFFFFF
(十进制的 4294967295)。因此,0x2021ABCD
是一个有效的值,可以被 unsigned int
类型的变量存储。)
#include <iostream>
int main() {
unsigned int num = 0x2021ABCD; // 将十六进制数赋值给unsigned int变量
std::cout << "The value of num is: " << num << std::endl;
return 0;
}
2.蓝桥1230进制转换
题目描述
给定一个N 进制数S,请你将它转换为M 进制。
输入描述
第一行为一个整数T,表示测试数据数量。 (1≤T≤10^5)
每个测试用例包含两行,第一行包含两个整数N,M。
第二行输入一个字符串S,表示N 进制数。
数据范围保证:2≤N,M≤16,若N≥10,则用A∼F 表示字码10∼15。保证S 对应的十进制数的位数不超过10。
输出描述
输出共T,每行表示一组数据的答案。
输入样例
2
2 10
10101
11 2
1793A5068
输出样例
21
10101111001010100111010101011
运行限制
最大运行时间:1s
最大运行内存: 128M
方法:先将N进制数转换为10进制数,再将10进制数转换为M进制数
代码:
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <limits>
#include <set>
#include <utility>
#include <vector>
#include <string>
using namespace std;
int turn(char x){
if(x>='0'&&x<='9'){
return x-'0';
}else if(x>='A'&&x<='F'){
return x-'A'+10;
}else if(x>='a'&&x<='f'){
return x-'a'+10;
}else{
return -1;
}
}
void reverse(string& str) {
size_t left = 0;
size_t right = str.length() - 1;
while (left < right) {
// 交换左右两端的字符
swap(str[left], str[right]);
// 移动指针
++left;
--right;
}
}
string NturnM(int x,int M){
string result;
int remain;
if(x==0){
return "0";
}
while(x>0){
remain=x%M;
result+=to_string(remain);
x/=M;
}
reverse(result);
return result;
}
int main()
{
int T;
cin>>T;
while(T--){
int N,M;
cin>>N>>M;
string S;
cin>>S;
int count=0;
int s=S.size();
for(int i=0;i<s;i++){
//cout<<str[i];
char x=S[i];
int y=turn(x);
count=count*N+y;
}
string str=NturnM(count,M);
cout<<str<<endl;
}
return 0;
}