算法笔记练习 5.6 大整数运算 问题 D: 进制转换

算法笔记练习 题解合集

题目链接

题目

题目描述
将M进制的数X转换为N进制的数输出。

输入
输入的第一行包括两个整数:M和N(2<=M,N<=36)。
下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成N进制的数输出。

输出
输出X的N进制表示的数。

样例输入

10 2
11

样例输出

1011

提示
注意输入时如有字母,则字母为大写,输出时如有字母,则字母为小写。

思路

整体步骤:
  1. mn接收两个整数,字符串buffer接收数 X;
  2. 通过baseChange函数将m进制的buffer字符串转换成bign类型的a
  3. basePrint函数输出an进制形式。

函数的思路:

关于大整数运算的基础(包括bign类型,大整数的四则运算等),参考算法笔记 P170。
这里仅描述数学上的思路,具体实现请看代码。

baseChange函数:

  1. 接收两个参数:字符串的首地址str,用base进制来解读;
  2. str的低位(即字符串末尾)开始遍历,第i位(记字符串末尾为第0位)代表的十进制数值是 s t r [ i ] × b a s e i str[i]\times base^i str[i]×basei,但是str[i]是字符类型,所以就需要一个函数char_to_int来做转换;
  3. 用步骤 2 把str上所有位置代表的十进制数值相加就得到了十进制的a

basePrint函数:

  1. 接收两个参数:bign类型的十进制数字a,用base进制来输出;
  2. 和普通的进制转换思路一样,只要a大于零,就不断地用base去除a,令a等于商并记录余数。由于先算出来的是高位,最后算出来的是低位,需要一个栈(普通数组)来存放结果;
  3. 最后不断弹出栈中的内容输出即可,需要一个int_to_char函数把数字转换成对应的字符。

细节:注意输入的字母是大写,输出是小写。

代码

#include 
#include 

#define MAX 2000

struct bign {
	int d[MAX];
	int len;
	bign() {
		memset(d, 0, sizeof(d));
		len = 0; 
	} 
};

int char_to_int(char c);				// 把数字字符或者大写字母转为对应的十进制 int 
char int_to_char(int n);				// 把十进制 int 转为对应的小写字母 

bign baseChange(char *str, int base);	// 把 base 进制的输入字符串转为十进制的 bign 
void basePrint(bign a, int base);		// 以 base 进制输出 a 

bign add(bign a, bign b);				// 高精度加高精度 
bign multi(bign a, int b);				// 高精度乘低精度
bign divide(bign a, int b, int &r);		// 高精度除以低精度,r为余数

int main() {
	int m, n;
	char buffer[MAX];
	while (scanf("%d %d", &m, &n) != EOF) {
		scanf("%s", buffer);
		bign a = baseChange(buffer, m);
		basePrint(a, n);
		putchar('\n'); 
	} 
	return 0;
} 

int char_to_int(char c) {	// 把数字字符或者大写字母转为对应的十进制 int 
	int ret;
	if (c >= '0' && c <= '9')
		ret = c - '0';
	else if (c >= 'A' && c <= 'Z')
		ret = c - 'A' + 10;
	return ret;
} 

char int_to_char(int n) {	// 把十进制 int 转为对应的小写字母 
	char ret;
	if (n >= 0 && n <= 9)
		ret = n + '0';
	else if (n >= 10 && n <= 35)
		ret = 'a' + n - 10; 
} 

bign baseChange(char *str, int base) {	// 把 base 进制的输入字符串转为十进制的 bign 
	bign a;
	a.len = 1;
	int len = strlen(str);
	int i;
	for (i = 0; i != len; ++i) {
		bign power;
		power.d[0] = 1;
		power.len = 1;
		for (int j = 0; j != i; ++j)	// 得到了 base 的 i 次方 
			power = multi(power, base);
		// 得到了数位上的字符对应的十进制数数值 
		power = multi(power, char_to_int(str[len - i - 1])); 
		a = add(a, power);
	} 
	return a;
} 

void basePrint(bign a, int base) {	// 以 base 进制输出 a 
	int output[MAX];
	int index = 0; 
	while (a.len != 1 || a.d[0] != 0) {
		a = divide(a, base, output[index]); 
		++index;
	} 
	for (--index ; index >= 0; --index)
		putchar(int_to_char(output[index])); 
} 

bign add(bign a, bign b) {
	bign c;
	int carry = 0;
	int len = (a.len > b.len) ? a.len : b.len;
	for (int i = 0; i != len; ++i) {
		int temp = a.d[i] + b.d[i] + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10; 
	}
	if (carry)
		c.d[c.len++] = carry;
	return c;
}

bign multi(bign a, int b) {
	bign c;
	int carry = 0;
	for (int i = 0; i != a.len; ++i) {
		int temp = b * a.d[i] + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10; 
	}
	while (carry) {
		c.d[c.len++] = carry % 10;
		carry /= 10;
	} 
	return c;
} 

bign divide(bign a, int b, int &r) {
	r = 0;
	bign c;
	c.len = a.len;
	for (int i = a.len - 1; i >= 0; --i) {
		r = r * 10 + a.d[i];
		if (r < b)
			c.d[i] = 0;
		else {
			c.d[i] = r / b;
			r %= b;
		}
	} 
	while (c.len - 1 >= 1 && c.d[c.len - 1] == 0)
		--c.len;
	return c;
} 

你可能感兴趣的:(算法笔记)