题目描述
写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入 )
输入一个十六进制的数值字符串。
输出该数值的十进制字符串。
解题思路
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>