进制转换 - 九度教程第62题

版权声明:本文为博主原创文章,未经博主允许不得转载。 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 为两个整数中较多的位数,即运算本身可能带来巨大的耗时。 所以,在计算复杂度时不能忽略对高精度运算的耗时估计。

猜你喜欢

转载自blog.csdn.net/LYKXHTP/article/details/88550869