• C++ 大数模板


    #include<stdio.h>//不能连续复合运算,要保存结果
    #include<stdlib.h>//所以一个技巧就是用strcpy来代替等号
    #include<string.h>//c=a+b改写为strcpy(c,BigAdd(a,b))
    #include <iostream>
    using namespace std;
    #define BASE 10    //确定进制
    #define N 90001    //确定 最大位数+1
    
    int l = 0;                //每次记录缓存区用了多长,还原时节省时间
    char res[N] = { '' };  //保存结果
    
    void ini(char * x , int l);   //初始化x数组
    int BigCmp(char * a, char * b);  //  大数a < 大数b 返回1 ,相等返回0 ,a>b返回-1
    void Clean(char * x, int l);//清除尾部的‘0’
    void rev(char * x);//倒置字符串 ,与Clean联用,清除前导0
    
    char * BigAdd(char * a, char * b);
    char * BigSub(char * a,char * b);
    char * BigMul(char * a,char * b);
    char * BigDivNum(char * num,int  n);//大数除以一个int
    char * BigDivBig(char * a,char * b);//大数除以一个大数
    
    char * BigPow(char *num ,int n);
    char * BigMod(char * num , int mod);
    char * BigFuc(int num);
    
    int main()
    {
        char a[N] = {''},b[N]={''};
        int n;
    
        while(~scanf("%s%s%d",a,b,&n))
        {
            cout<<"a+b="<<" ";
            puts(BigAdd(a,b));
    
            cout<<"a-b="<<" ";
            puts(BigSub(a,b));
    
            cout<<"a*b="<<" ";
            puts(BigMul(a,b));
    
            cout<<"a/b="<<" ";
            puts(BigDivBig(a,b));
    
            cout<<"a/n="<<" ";
            puts(BigDivNum(a,n));
    
            cout<<"a^n="<<" ";
            puts(BigPow(a,n));
    
            cout<<"a%n="<<" ";
            puts(BigMod(a,n));
    
            cout<<"n!="<<" ";
            puts(BigFuc(n));
    
            puts("");
        }
        return 0;
    }
    
    char *  BigAdd( char * a, char * b)
    {
        int i,j,k;
        int sum,la,lb,carry,flag,cmp;
        char *ans,*temp;
    
        ini(res,l);
        carry = 0;
        flag = 0;
        ans = &res[1];
    
        if(a[0] == '-' && b[0] != '-')         //判断正负
            return BigSub(b,a+1);
        else if(a[0] != '-' && b[0] == '-')
            return BigSub(a,b+1);
        else if(a[0] == '-' && b[0] == '-')
        {
            flag = 1;
            a++;
            b++;
        }
    
        la=strlen(a);
        lb=strlen(b);
    
        if(b[0] == '0' && lb == 1)     //判断0
        {
            strcpy(ans,a);
            l = strlen(ans);
            return ans;
        }
        else if(a[0] == '0' && la ==1)
        {
            strcpy(ans,b);
            l = strlen(ans);
            return ans;
        }
    
        rev(a);
        rev(b);
    
        if(BigCmp(a,b) == 1)     //保持大数a>大数b
        {
            temp = a;
            a = b;
            b =temp;
    
            k = la;
            la = lb;
            lb = k;
        }
    
        for(i = lb ; i < la ; i++)  //空位补0
            b[i] = '0';
    
        for(i = 0 ; i < la ; i++)
        {
            sum = (a[i]-48) + (b[i]-48) + carry;
    
            if( sum < BASE )
            {
                ans[i] = sum + 48;
                carry = 0;
            }
            else
            {
                ans[i] = sum  - BASE  + 48;
                carry = 1;
            }
        }
    
        if(carry)   //补充最高位
        {
            ans[i] = carry + 48;
            i++;
        }
    
        Clean(ans,i);
    
        for(i = lb ; i < la ; i++)//删除后补上的0
            b[i] = '';
    
        rev(ans);
        rev(a);
        rev(b);
    
        if(flag)
        {
            res[0] = '-';
            ans = res;
        }
    
        l = strlen(ans);
        return ans;
    }
    
    char * BigSub(char * a,char * b)
    {
        char *ans,*temp;
        int i,j,k;
        int borrow,flag,la,lb,sub,cmp;
    
        ini(res,l);
        ans = &res[1];
    
        flag = 0;  //结果没有负号
        borrow = 0;
    
        if(a[0]=='-' && b[0]!='-')  //被减数为负,减数为正,结果为负
        {
            BigAdd(b,a+1);
            res[0] = '-';
            return  res;
        }
        else if(a[0]!='-' && b[0]=='-') //被减数为正,减数为负,结果为正
            return BigAdd(a,b+1);
        else if(a[0]=='-' && b[0]=='-')   //如果a,b为同时负,交换他们并都改为正,保证为“a-b”的形式
        {
            temp=a;
            a=b;
            b=temp;
    
            a++;
            b++;
        }
    
        la = strlen(a);
        lb = strlen(b);
    
        if(b[0] == '0' && lb == 1)     //判断0
        {
            l = strlen(strcpy(ans,a));
            return ans;
        }
        else if(a[0] == '0' && la == 1)
        {
                if(b[0] == '-')
                {
                    l = strlen(strcpy(ans,b+1));
                    return ans;
                }
                else
                {
                    res[0] = '-';
                    l = strlen(strcpy(ans,b));
                    return res;
                }
        }
    
        cmp = BigCmp(a,b);
    
        if(cmp == 0)
        {
            l = 1;
            res[0] = '0';
            res[1] = '';
            return res;
        }
        else if(cmp == 1)  //保持大数a>=大数b
        {
            temp=a;
            a=b;
            b=temp;
            flag=1;  //结果有负号
    
            k = la;
            la = lb;
            lb = k;
        }
    
        rev(a);
        rev(b);
    
        for(i=0; i<lb ; i++)
        {
            sub = a[i] - borrow - b[i];
    
            if( sub >= 0)
            {
                ans[i] = sub + 48;
                borrow = 0 ;
            }
            else    // 溢出时的计算方法
            {
                ans[i]   = sub + BASE + 48;
                borrow = 1;
            }
        }
    
        while(i < la)   // 计算剩余位
        {
            sub = a[i] - borrow ;
    
            if(a[i] >= borrow)
            {
                ans[i]   = sub ;
                borrow = 0;
            }
            else        // 溢出时的计算方法
            {
                ans[i]  = sub +BASE ;
                borrow = 1;
            }
             i++;
        }
    
        Clean(ans,i);
    
        rev(ans);
        rev(a);
        rev(b);
    
        if(flag)
        {
            res[0] = '-';
            ans = res;
        }
    
        l = strlen(ans);
        return ans;
    }
    
    char * BigMul(char * a,char * b)
    {
        char *temp,*ans;
        char mul[N] = {''},cal[N] = {''},num[N] = {''};
        int i,j,k;
        int carry,flag,la,lb,product,lmul;
        int sign,sign_a,sign_b;
    
        ini(res,l);
        ans = &res[1];
    
        carry = 0;
        flag = 0;
        sign = sign_a = sign_b = 0;
    
        if(a == b)   //重复拷贝
            b = strcpy(num,a);
    
        if(a[0] == '-' )
        {
            flag = 1;
            sign_a = 1;
            a++;
        }
        if(b[0] == '-' )
        {
            flag = 1;
            sign_b = 1;
            b++;
        }
        if(sign_a && sign_b)
            flag = 0;
    
        la = strlen(a);
        lb = strlen(b);
    
        if((a[0] == '0' && la == 1) || (b[0] == '0' && lb == 1))  //任何一个大数为0,结果为0
        {
            l = 1;
            res[0] = '0';
            res[1] = '';
            return res;
        }
    
        if(BigCmp(a,b) == 1)   //保证大数a >= 大数b
        {
            temp = a;
            a = b ;
            b = temp;
    
            k = la;
            la = lb;
            lb =k;
        }
    
        rev(a);
        rev(b);
    
        Clean(a,la);//清除自带的前导0
        Clean(b,lb);
        la = strlen(a);//重新计算长度
        lb = strlen(b);
    
        lmul = 0;
    
        for(i = 0 ; i < lb ; i++)
        {
            ini(mul,lmul);
    
            for( j = 0 ; j < la ; j++)
            {
                product = (a[j] - 48) * (b[i] - 48) + carry ;
                mul[j] = product % BASE + 48 ;
                carry = product / BASE ;
            }
    
            if(carry)
            {
                mul[j] = carry + 48;
                j++;
    
                carry = 0;
            }
    
            lmul = j;  //计算缓冲区长度
    
            if(i == 0)
            {
                strcpy(cal,mul);
                rev(cal);
            }
            else
            {
                //清除前导0
                Clean(mul,lmul);
                //翻转字符串
                rev(mul);
                //以0补位,每次相当于乘10
                for(k = 0 ; k < i ;k++)
                    mul[lmul++] = '0';
                //保存
                ans = BigAdd(cal,mul);
                ini(cal,strlen(cal));
                strcpy(cal,ans);
            }
        }
        strcpy(ans,cal);
    
        rev(a);
        rev(b);
    
        if(flag)
        {
            res[0] = '-';
            ans = res;
        }
        l = strlen(ans);
        return ans;
    }
    
    char * BigDivBig(char * a,char * b)
    {
        char *ans, *temp;
        int i,j,k,la,lb,cmp,times,tran_min;
        int sign,sign_a,sign_b,flag;
    
        ini(res,l);
        ans = &res[1];
        sign_a = sign_b = flag = 0;
    
        if(a[0] == '-')
        {
            sign_a = flag = 1;
            a++;
        }
        if(b[0] == '-')
        {
            sign_b = flag = 1;
            b++;
        }
        if(sign_a && sign_b)
            flag = 0;
        la = strlen(a);
        lb = strlen(b);
    
        rev(a);
        rev(b);
        Clean(a,la);
        Clean(b,lb);
        rev(a);
        rev(b);
    
        la = strlen(a);
        lb = strlen(b);
    
        if(la == 1 && a[0] == '0')
        {
            l = 1;
            res[0] = '0';
            res[1] = '';
            return res;
        }
        if(lb == 1 && b[0] == '0')
        {
            puts("除数不能为0!");
            exit(1);
        }
        if(lb == 1 && b[0] == '1')
        {
            l = strlen(strcpy(res,a));
            return res;
        }
    
        cmp = BigCmp(a,b);
        if(cmp == 1)
        {
            l = 2;
            ans[0] = '0';
            ans[1] = '';
            return ans;
        }
        else if(cmp == 0)
        {
            l = 2;
            ans[0] = '1';
            ans[1] = '';
            if(flag)
            {
                res[0]='-';
                ans = res;
            }
            return ans;
        }
        ///对齐最高位试除
        char pre[N] = {''},num[N] = {''},now[N] = {''},tran[N] = {''};
        char mul[N] = {''},sub[N] = {''},div[N]={''};
        char carry[N] = {'0'};///注意是 0
        memset(carry,'0',sizeof(carry));
        now[0] = '0'; //大数now初始化为0
        carry[0] = '1';//大数carry初始化为1000000000……
        times = la - lb;//确定最高倍数
        strcpy(num,a);  //复制a的值
        strcpy(div,b);//复制b的值
        for(i = 0 ; i < times ; i++) //对齐最高位
                div[lb+i] = '0';
    
        for(i = times ; i >= 0 ;i--)
        {   //最小的倍数为:a最高位/(b最高位+1),试一下就知道了
            tran_min = (num[0] - '0')/(div[0]-'0'+1);   ///?????
            for(j = 9 ; j >= tran_min ; j--)
            {
                sprintf(tran,"%d",j); //把试乘值转换成字符串
                strcpy(pre,BigMul(div,tran));
                strcpy(sub,BigSub(num,pre)); //sub = a - b*j;
                //从大到小找第一个可以被减的数
                if(sub[0] != '-')
                {
                    carry[i+1] = ''; //截断carry得到倍数
                    strcpy(mul,BigMul(carry,tran));//乘上这次的值
                    strcpy(now,BigAdd(now,mul));//将商保存在now中
                    strcpy(num,sub);   //更新a的值
                    break;
                }
            }
            div[lb+i-1] = ''; //每次循环降低一位直至复原
            memset(res,'',sizeof(res));
        }
        strcpy(ans,now);
        if(flag)
        {
            res[0] = '-';
            ans = res;
        }
        l = strlen(ans);
        return ans;
    }
    
    char * BigDivNum(char * num , int n)
    {
        char * ans;
        int i,j,digit,divis,lnum,flag;
        int sign_num,sign_n;
    
        ini(res,l);
    
        ans = &res[1];
    
        digit = divis = flag = 0;
        sign_num = sign_n = 0;
    
        if(n == 0)
        {
            puts("除数不能等于0");
            exit(1);
        }
    
        if(n < 0)
        {
            n = -n;
            flag = 1;
            sign_n = 1;
        }
        if(num[0] == '-')
        {
            num++;
            flag = 1;
            sign_num = 1;
        }
        if(sign_n && sign_num)
            flag = 0;
    
        lnum = strlen(num);
    
        if(lnum == 1 && num[0] == '0')
        {
            l = 1;
            res[0] = '0';
            res[1] = '';
            return res;        //被除数为0,结果为0
        }
    
        for(i = 0 ; i < lnum ; i++)
        {
            divis = divis * 10 + (num[i]-48) ;
    
            if(divis >= n)
            {
                ans[digit++] = divis / n + 48;
                divis %= n;
            }
        }
    
        if(!digit)
            ans[digit++] = '0';
    
        ans[digit] = '';
    
        if(flag)
        {
            res[0] = '-';
            ans = res;
        }
        l = strlen(ans);
        return ans;
    }
    
    char * BigPow(char * num, int n)
    {
        char  * ans;
        char cal[N] = {''},pow[N] = {''};
        int  flag;
    
        if(n == 0)
        {
            l = 1;
            res[0] = '1';
            res[1] = '';
            return res;
        }
    
        if(strlen(num) == 1 && num[0] == '0')
        {
            l = 1;
            res[0] = '0';
            res[1] = '';
            return res;
        }
    
        ini(res,l);
        ans = &res[1];
    
        flag = 0;
    
        strcpy(pow,num); //备份
        cal[0] = '1';
    
        if(pow[0] == '-' && n&1)
            flag = 1;
    
        while(n)
        {
            if(n&1)
            {
                ans = BigMul(cal,num);
    
                ini(cal,strlen(cal));
                strcpy(cal,ans);
            }
    
            ans = BigMul(num,num);
    
            ini(num,strlen(num));
            strcpy(num,ans);
    
            n >>= 1;
        }
        strcpy(num,pow); //还原
    
        strcpy(ans,cal);
        if(flag)
        {
            res[0] = '-';
            ans = res;
        }
        l = strlen(ans);
        return ans;
    }
    
    char * BigMod(char * num , int mod)
    {
        char * ans;
        int i,lnum,cal;
    
        if(mod == 0)
        {
            puts("除数不能等于0");
            exit(1);
        }
    
        ini(res,l);
    
        ans = &res[1];
        cal = 0;
    
        lnum = strlen(num);
    
        for(i = 0 ; i < lnum ; i++)     //循环利用同余定理
            cal = ( ((cal*BASE)%mod) + ((num[i]-48)%mod) ) % mod ;
    
        sprintf(ans,"%d",cal);  //转换为字符串
        l = strlen(ans);
        return ans;
    }
    
    char * BigFuc(int num)
    {
        int i,j,k;
        int digit,carry,temp;
        char * ans;
    
        ini(res,l);
        ans = &res[1];
    
        if(num == 0)
        {
            l = 1;
            res[0] = '1';
            res[1] = '';
            return res;
        }
    
        ans[0] = '1';
        digit = 1;
    
        for(i = 2 ; i <= num ; i++)
        {
            carry = 0;  //初始化为0
    
            for(j = 0 ; j < digit ; j++)
            {
                temp = (ans[j]-48)* i + carry; //中间值
    
                ans[j] = temp % BASE +48 ;
                carry = temp / BASE;
            }
    
            while(carry)  //处理剩余位数
            {
                ans[digit++] = carry % BASE + 48;
                carry /= BASE ;
            }
        }
    
        rev(ans);
    
        l = strlen(ans);
        return ans;
    }
    
    int BigCmp(char * a, char * b)  //  大数a < 大数b 返回1 ,相等返回0 ,a>b返回-1
    {
        int i,j,k;
        int la = strlen(a),lb = strlen(b);
        char * temp;
    
        if(a[0] == '-' && b[0] != '-')
            return 1;
        else if(a[0] != '-' && b[0] == '-')
            return -1;
        else if(a[0] == '-' && b[0] == '-')
        {
            a++;
            b++;
    
            temp = a;
            a = b;
            b = temp;
    
            la--;
            lb--;
    
            k = la;
            la =lb;
            lb = k;
        }
    
        if(la < lb)
            return 1;
        if(la > lb)
            return -1;
    
        if(la == lb)
        {
            for(i = 0 ; i < la ; i++)
            {
                if(a[i] < b[i])
                    return 1;
                else if(a[i] > b[i])
                    return -1;
            }
        }
    
        return 0;
    }
    
    void ini(char * x ,int l)
    {
        int i;
    
        if(l < N)
            l++;
    
        for(i = 0 ; i < l ;i++)
            x[i] = '';
    }
    
    void Clean(char * x,int l)
    {
        for(l--; x[l] == '0';l--)
            x[l] = '';
    }
    
    void rev(char * x)
    {
        int right = strlen(x)-1;
        int left = 0;
        char temp;
    
        while(left < right)
        {
            temp = x[left];
            x[left++] = x[right];
            x[right--] = temp;
        }
    }
    View Code
    每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
  • 相关阅读:
    【python笔记】类
    【Marva Collins' Way】第八章
    【Marva Collins' Way】第七章
    【python笔记】包
    【python笔记】模块
    【Marva Collins' Way】第六章
    【Marva Collins' Way】第九章
    【python笔记】异常
    Axios跨域&封装接口
    js更新数据
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/9332825.html
Copyright © 2020-2023  润新知