数的进制转换(任意两个进制之间的转换)

编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。

这里有62个不同数位{0-9,A-Z,a-z}。

输入格式

第一行输入一个整数,代表接下来的行数。

接下来每一行都包含三个数字,首先是输入进制(十进制表示),然后是输出进制(十进制表示),最后是用输入进制表示的输入数字,数字之间用空格隔开。

输入进制和输出进制都在2到62的范围之内。

(在十进制下)A = 10,B = 11,…,Z = 35,a = 36,b = 37,…,z = 61 (0-9仍然表示0-9)。

输出格式

对于每一组进制转换,程序的输出都由三行构成。

第一行包含两个数字,首先是输入进制(十进制表示),然后是用输入进制表示的输入数字。

第二行包含两个数字,首先是输出进制(十进制表示),然后是用输出进制表示的输入数字。

第三行为空白行。

同一行内数字用空格隔开。

输入样例:

8
62 2 abcdefghiz
10 16 1234567890123456789012345678901234567890
16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 23 333YMHOUE8JPLT7OX6K9FYCQ8A
23 49 946B9AA02MI37E3D3MMJ4G7BL2F05
49 61 1VbDkSIMJL3JjRgAdlUfcaWj
61 5 dl9MDSWqwHjDnToKcsWE1S
5 10 42104444441001414401221302402201233340311104212022133030

输出样例:

62 abcdefghiz
2 11011100000100010111110010010110011111001001100011010010001

10 1234567890123456789012345678901234567890
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2

16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 333YMHOUE8JPLT7OX6K9FYCQ8A

35 333YMHOUE8JPLT7OX6K9FYCQ8A
23 946B9AA02MI37E3D3MMJ4G7BL2F05

23 946B9AA02MI37E3D3MMJ4G7BL2F05
49 1VbDkSIMJL3JjRgAdlUfcaWj

49 1VbDkSIMJL3JjRgAdlUfcaWj
61 dl9MDSWqwHjDnToKcsWE1S

61 dl9MDSWqwHjDnToKcsWE1S
5 42104444441001414401221302402201233340311104212022133030

5 42104444441001414401221302402201233340311104212022133030
10 1234567890123456789012345678901234567890

思路:转十进制的同时短除法(相当于直接短除) 

进制转换函数:

void change(int a,string s1,int b,string &s2)//将a进制的s1转换成b进制的s2
{
    vector<int>num;
    for(int i=0;i<s1.size();i++){
        if(s1[i]<='9') num.push_back(s1[i]-'0');
        else if(s1[i]<='Z') num.push_back(s1[i]-'A'+10);
        else num.push_back(s1[i]-'a'+36);
    }
    reverse(num.begin(),num.end());//从低位到高位来存
    vector<int>ans;
    while(num.size()){//短除法,直到商0为止,即:num.empty
        int r=0;//r为每次短除法运算的余数
        for(int i=num.size()-1;i>=0;i--){//整个循环为一次短除法的运算,num中的数是从低位到高位来存的,倒过来从高位到底位符合除法顺序
            num[i]+=r*a;//当前被除数等于((上一次的余数*a)+(当前位的数))<==>(转十进制))
            r=num[i]%b;//取本次余数,作为下一次被除数那一部分的基数
            num[i]/=b;//统计计算本次运算后num的值
        }
        ans.push_back(r);//将本次运算最后余数作为答案的这一位的值(这里是从低位到高位存的,因为短除法是逆序的)
        while(num.size()&&num.back()==0) num.pop_back();//去除前导零(正是因为vector只有pop_back没有pop_front,所以从低位到高位来存)
    }
    reverse(ans.begin(),ans.end());//因为ans是从低位到高位存的,所以最后要反过来
    for(int i=0;i<ans.size();i++){
        if(ans[i]<=9) s2+=char(ans[i]+'0');
        else if(ans[i]<=35) s2+=char(ans[i]-10+'A');
        else s2+=char(ans[i]-36+'a');
    }
}

完整代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

void change(int a,string s1,int b,string &s2)//将a进制的s1转换成b进制的s2
{
    vector<int>num;
    for(int i=0;i<s1.size();i++){
        if(s1[i]<='9') num.push_back(s1[i]-'0');
        else if(s1[i]<='Z') num.push_back(s1[i]-'A'+10);
        else num.push_back(s1[i]-'a'+36);
    }
    reverse(num.begin(),num.end());//从低位到高位来存
    vector<int>ans;
    while(num.size()){//短除法,直到商0为止,即:num.empty
        int r=0;//r为每次短除法运算的余数
        for(int i=num.size()-1;i>=0;i--){//整个循环为一次短除法的运算,num中的数是从低位到高位来存的,倒过来从高位到底位符合除法顺序
            num[i]+=r*a;//当前被除数等于((上一次的余数*a)+(当前位的数))<==>(转十进制))
            r=num[i]%b;//取本次余数,作为下一次被除数那一部分的基数
            num[i]/=b;//统计计算本次运算后num的值
        }
        ans.push_back(r);//将本次运算最后余数作为答案的这一位的值(这里是从低位到高位存的,因为短除法是逆序的)
        while(num.size()&&num.back()==0) num.pop_back();//去除前导零(正是因为vector只有pop_back没有pop_front,所以从低位到高位来存)
    }
    reverse(ans.begin(),ans.end());//因为ans是从低位到高位存的,所以最后要反过来
    for(int i=0;i<ans.size();i++){
        if(ans[i]<=9) s2+=char(ans[i]+'0');
        else if(ans[i]<=35) s2+=char(ans[i]-10+'A');
        else s2+=char(ans[i]-36+'a');
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        int a,b;
        string s1,s2;
        cin>>a>>b>>s1;
        change(a,s1,b,s2);
        cout<<a<<" "<<s1<<endl;
        cout<<b<<" "<<s2<<endl;
        cout<<endl;
    }
    return 0;
}
发布了176 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Mr_Kingk/article/details/104433823