题目描述

写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入 )
输入一个十六进制的数值字符串。
输出该数值的十进制字符串。

解题思路

u1s1,如果从解题的角度,这题目是真的简单,因为基本上我学过的三门语言(C,C++,Python)中都提供了从输入流中读取十六进制数的方法。

// C 
scanf("%x", &num) ;
// C++
C++: cin >> hex >> num ;

// Python3
num = int(input(), 16)

但是这里有一个问题就是说在C/C++中整数存在上限,即便是unsigned long型也最大只能表示2^64-1。因此对于输入的16进制数值字符串不应该直接转换为整型数,而应该考虑大数运算(题目并没有考虑)。

代码实现

现在先给出不考虑大整数的通用解法(C++):其他进制转10进制
首先给出数字到字符,和字符到数字的映射

// 两个全局数组
char Num2Char[] = "0123456789abcdefghijklmnopqrstuvwxyz" ;
// 数组Char2Num可以通过循环语句初始化
int Char2Num[127] = {
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5 ,
['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['a'] = 10, ['b'] = 11,
['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15, ['g'] = 16, ['h'] = 17, 
['i'] = 18, ['j'] = 19, ['k'] = 20, ['l'] = 21, ['m'] = 22, ['n'] = 23,
['o'] = 24, ['p'] = 25, ['q'] = 26, ['r'] = 27, ['s'] = 28, ['t'] = 29,
['u'] = 30, ['v'] = 31, ['w'] = 32, ['x'] = 33, ['y'] = 34, ['z'] = 35,
}  ;

对于其他进制转10进制,只需要将对应的位置的数字乘以相应的权值

int Other2Dec(string numstr, int base)
{   
    int sum = 0 ; 
    for(auto ch : numstr)
        sum = (sum * base) + Char2Num[(int)ch] ;
    return sum ;
}

10进制转其他进制,可以通过不断对数字做除法实现。由于得到的余数序列是反序的,因此用栈实现。

string Dec2Other(int num, int base)
{
    stack<int> st ;
    while(num > 0){
        st.push(num % base) ;
        num = num / base ;
    }
    string re = "";
    while(st.empty() != true){
        re += Num2Char[st.top()] ;
        st.pop() ;
    }
    return re ;
}

如果要实现16进制数值字符串转10进制,只需要封装一下就好了

int Hex2Dec(string s)
{
    // 如果串s中含前缀
    s.erase(s.begin(), s.begin()+2) ;
    return Other2Dec(s, 16) ;
}

现在考虑大数,如果输入的16进制数超过了C++能够表示的整数范围,那么使用字符串表示十进制整数,字符串的每1位表示一个十进制位。

// 大数乘以整型数
string MUL(string s, int num)
{
    reverse(s.begin(), s.end()) ;
    int Carry = 0 ;
    for(int i = 0; i < s.length(); i++){
        int temp = Char2Num[(int)s[i]] * num + Carry ;
        s[i] = Num2Char[temp % 10];
        Carry = temp / 10 ;
    }
    cout << Carry << endl ;
    while(Carry > 0){
        s.push_back(Num2Char[Carry % 10]) ;
        Carry /= 10 ;
    }
    reverse(s.begin(), s.end()) ;
    return s ;
}
// 大数加整型数
string ADD(string s, int num)
{
    reverse(s.begin(), s.end()) ;
    int Carry = 0 ;
    int i     = 0 ;
    int temp = Char2Num[(int)s[i]] + num ;
    do{
        if(i >= s.length()){
            s.push_back(Num2Char[temp % 10]) ;
        }else{
            s[i] = Num2Char[temp % 10] ;
        }
        Carry = temp / 10 ;
        temp = Char2Num[(int)s[++i]] + Carry ;
    }while(Carry != 0) ;
    reverse(s.begin(), s.end()) ;
    return s ;
}
// 其他进制转10进制数
string Other2Dec(const string &hexstr, int base)
{
    string sum ;
    for(auto ch : hexstr)
        sum = ADD(MUL(sum, base), Char2Num[int(ch)]) ;
    return sum ;
}

实际上只是更改了数据结构和对应的操作算法,框架是一样的,每个位置上的其他进制符号乘以对应的权值,最后计算和。算法的效率相对较低,因为1个字节只表示一个10进制位,可以vector<int>数据额类型,每一个4个字节的int类型(最大表示2^31-1)),可以表示10个10进制位。</int>