版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LYKXHTP/article/details/88550869
进制转换 - 九度教程第62题
题目
时间限制:1 秒 内存限制:32 兆 特殊判题:否
题目描述:
将 M 进制的数 X 转换为 N 进制的数输出。
输入:
输入的第一行包括两个整数:M 和 N(2<=M,N<=36)。
下面的一行输入一个数 X,X 是 M 进制的数,现在要求你将 M 进制的数 X 转换成 N 进制的数输出。
输出:
输出 X 的 N 进制表示的数。
样例输入:
16 10
F
样例输出:
15
提示:
输入时字母部分为大写,输出时为小写,并且有大数据。
来源:
2008年清华大学计算机研究生机试真题
该题初看起来很像一般的进制转换,但提示中明确告知,输入会有较大的数据,即为了完成需要的进制转换,需要使用高精度整数。同时,考虑到进制转换的内容,高精度整数需要进行以下运算:高精度整数与普通整数的求积,高精度整数之间求和,高精度整数除以普通整数,高精度整数对普通整数求模等。
#include <stdio.h>
#include <string.h>
#define maxDigits 100
struct bigInteger{//高精度整数结构体
int digit[maxDigits];
int size;
void init(){//初始化
for(int i=0;i<maxDigits;i++)digit[i]=0;
size=0;
}
void set(int x){//用一个普通整数初始化高精度整数
init();
do{
digit[size++]=x%10000;
x/=10000;
}while(x!=0);
}
void output(){
for(int i=size-1;i>=0;i--){
if(i!=size-1)printf("%04d",digit[i]);
else printf("%d",digit[i]);
}
printf("\n");
}
bigInteger operator * (int x) const{
//高精度整数与普通整数的乘法
bigInteger ret;
ret.init();
int carry=0;
for(int i=0;i<size;i++){
int tmp=x*digit[i]+carry;
carry=tmp/10000;
tmp%=10000;
ret.digit[ret.size++]=tmp;
}
if(carry!=0){
ret.digit[ret.size++]=carry;
}
return ret;
}
bigInteger operator + (const bigInteger &A) const{
//高精度整数之间的加法运算
bigInteger ret;
ret.init();
int carry=0;
for(int i=0;i<A.size || i<size;i++){
int tmp=A.digit[i]+digit[i]+carry;
carry=tmp/10000;
tmp%=10000;
ret.digit[ret.size++]=tmp;
}
if(carry!=0){
ret.digit[ret.size++]=carry;
}
return ret;
}
bigInteger operator / (int x) const{
//高精度整除除以普通整数
bigInteger ret;
ret.init();
int remainder=0;//余数
for(int i=size-1;i>=0;i--){
//从最高位至最低位依次完成计算
int t=(remainder*10000+digit[i])/x;
//计算当前位数值加上高位剩余的余数的和对x求得的商
int r=(remainder*10000+digit[i])%x;
//计算当前位数值加上高位剩余的余数的和对x求模后得到的余数
ret.digit[i]=t;//保存本位的值
remainder=r;//保存至本位为止的余数
}
ret.size=0;
//返回高精度整数的size初始值为0,
//即当所有位数数字都为0时,digit[0]代表数字0,
//作为最高有效位,高精度整数即为数字0
for(int i=0;i<maxDigits;i++){
if(digit[i]!=0)ret.size=i;
//若存在非0位,确定最高的非0位,作为最高有效位
}
ret.size++;
//最高位有效位的下一位即为下一个不曾使用的digit数组单元
//确定为size的值
return ret;
}
int operator % (int x) const{
//高精度整数对普通整数求余数
int remainder=0;//余数
for(int i=size-1;i>=0;i--){
//int t=(remainder*10000+digit[i])/x;
int r=(remainder*10000+digit[i])%x;
remainder=r;
}
return remainder;//返回余数
}
}a,b,c;
char str[10000];
char ans[10000];
int main()
{
int n,m;
while(scanf("%d%d",&m,&n)!=EOF){
scanf("%s",str);
int L=strlen(str);
a.set(0);
//a初始值为0,用来保存转换为10进制的m进制数
b.set(1);
//b初始值为1,在m进制向10进制转换的过程中,依次代表每一位权重
for(int i=L-1;i>=0;i--){
//由低位至高位转换m进制数至对应的10进制数
int t;
if(str[i]>='0' && str[i]<='9'){
t=str[i]-'0';
}else{
t=str[i]-'A'+10;
}
a=a+b*t;//累加当前数字乘以当前权重的积
b=b*m;//计算下一位权重
}
int size=0;//代表转换为n进制后的字符个数
do{//对转换后的10进制数求其n进制值
int t=a%n;//求余数
if(t>=10)ans[size++]=t-10+'a';
else ans[size++]=t+'0';
a=a/n;
}while(a.digit[0]!=0 || a.size!=1);
//当a不为0时重复该过程
for(int i=size-1;i>=0;i--){
printf("%c",ans[i]);
}
printf("\n");
}
return 0;
}
实现高精度整数的各种运算,归根到底还是利用加减乘除的运算法则,对高精度整数的各位模拟该运算规律。
另外若是只需求出一个高精度整数除以一个小数后余下的整数,可以使用如下代码:
int ans = 0;
//其中高精度大整数由高位至低位保存在字符数组str中,
//小整数保存在mod中
fo (int i = 0;str[i];i + r +) {
ans *= 10;
ans += str[i] - '0';
ans %= mod;
}
printf("%d\n",ans); //ans即为计算后剩下的余数
使用了高精度整数后,其程序就不能忽略运算本身带来的复杂度。如有高精度整数 a、b,则求 a+b 的和就不再能再在常数时间里得到结果,由于其高精度运算需要计算每一位的和,所以该运算复杂度变为 O (size),其中 size 为两个整数中较多的位数,即运算本身可能带来巨大的耗时。 所以,在计算复杂度时不能忽略对高精度运算的耗时估计。