大整数运算---模拟笔算

来源:互联网 发布:mac上的抠图软件 编辑:程序博客网 时间:2024/04/28 10:50
/**m=a[k]×10k-1+a[k-1]×10k-2+….+a[2]×10+a[1]*其中a[0]保存该长整数的位数。**模拟笔算*/#include<iostream>#include<cstring>using namespace std;#define SIZE 255void getl(char* n);//获取长整数void prt(char* n);//打印长整数int cmp(char* n1, char* n2);//比较长整数大小void swap(char * n);//长整数位交换void cpy(char* n1, char* n2);//复制长整数/**********************************************///乘法void mul(char* n1, char* n2);void muld(char* n, int t, char num);//位乘/**********************************************///除法void div(char* n1, char* n2, char* q);/**********************************************///加法void plu(char* n1, char* n2);int plua(char* n, int off, char num);//位加/**********************************************///减法int sub(char* n1, char* n2);//返回0正1负int suba(char* n1, int off, char num);//位减/**********************************************/int main(int argc, char** argv){cout<<"长整数乘除法运算。"<<endl<<endl;while(1){cout<<"请选择运算: 1.乘法; 2.除法。"<<endl;int t;//t=2;cin>>t;if(t == 1){cout<<"请依次输入 被乘数、乘数。"<<endl;}else if(t == 2){cout<<"请依次输入 被除数、除数。"<<endl;}else{cout<<"输入错误,请重试。";continue;}fflush(stdin);char n1[SIZE]={0},n2[SIZE]={0};getl(n1);getl(n2);if(t == 1){mul(n1, n2);cout<<"结果:";prt(n1);}else{            char q[SIZE] = {0};if(n2[0]==1 && n2[1]==0){cout<<"输入错误:除数不能为0"<<endl;continue;}            div(n1, n2, q);            cout<<"商:";prt(n1);cout<<"余数:";            prt(q);}}return 0;}/**********************************************/void getl(char* n){//从console获取一个长整数char tmp;while(tmp = getchar()){if(tmp <= '9'&&tmp >= '0'){break;}}int i=1;while(tmp <= '9'&&tmp >= '0'){n[i] = tmp;n[i] -= '0';tmp = getchar();i++;}n[0] = i-1;swap(n);}void prt(char* n){    //打印一个大整数if(n[0] == 0){cout<<"0";}    for(int i=n[0];i >= 1; i--){        cout<<char(n[i] + '0');    }    cout<<endl;}int cmp(char* n1, char* n2){    //比较两个大整数的大小 n1>n2返回1    if(n1[0] > n2[0]){        return 1;    }else if(n1[0] < n2[0]){        return -1;    }else{        for(int i=n1[0]; i>=1; i--){            if(n1[i] == n2[i]){                continue;            }else{                if(n1[i] > n2[i]){                    return 1;                }else{                    return -1;                }            }        }    }    return 0;}void swap(char* n){//按脚码逆置一个大整数char tmp;for(int i=1; i<=n[0]/2; i++){tmp = n[i];n[i] = n[n[0] - i + 1];n[n[0] - i + 1] = tmp;}}void cpy(char* n1, char* n2){//将n1复制为n2for(int i=0; i<=n2[0]; i++){n1[i] = n2[i];}}/**********************************************/void mul(char* n1, char* n2){//乘法,结果保存在n1char result[SIZE] = {0};char tmp[SIZE] = {0};for(int i=1; i<=n2[0]; i++){cpy(tmp, n1);muld(tmp, i - 1, n2[i]);plu(result, tmp);}cpy(n1, result);}void muld(char* n, int t, char num){//个位数乘,将n乘以 后跟t个零的个位数num,完成进位char k = 0;//进位数int i;for(i = 1; i<=n[0]; i++){n[i] *= num;n[i] += k;if(n[i] > 9){k = n[i]/10;n[i] %= 10;}else{k = 0;}}if(k){n[0]++;n[i] = k;}//左移for(int i=n[0]; i>=1; i--){n[i+t] = n[i];}for(int i=1; i<=t; i++){n[i] = 0;}n[0] += t;}/**已废弃int mula(char* n, int off, char num){//位乘,将n偏移为off的地方乘上num,返回进位n[off] *= num;cout<<"off "<<off<<endl;logi("n[off] ",n[off]%10);logi("num ",num);if(n[off] > 9){n[off] %= 10;return n[off]/10;}else{return 0;}}void mulplu(char* n, int off, char num){//乘法中用到的加法,将n偏移为off的位加上num,完成进位,结果保存在nint i;char k = n[off];for(i=off; k||i==off; i++){k = plua(n, i, k);}//i:最前面的不是进位的偏移if(i-2 > n[0]){n[0] = i-2;}}*//**********************************************//*从n1最高位开始余数=0while(可以向右截取){    余数 加上向右取的    while(取得的数小于n2){        向右取    }    while(余数 >= n2){        商++        余数 -= n2    }商放在结果的 截取位的最右位余数乘以10}*/void div(char* n1, char* n2, char* q){//除法,商保存在n1,余数保存在qchar remd[SIZE] = {0};//余数    char ans[SIZE] = {0};//结果    char d[SIZE] = {0};//截取的一位数d[0] = 1;char ten[SIZE] = {0};//长整数10ten[0] = 2;ten[1] = 0;ten[2] = 1;//保存未乘10的个位余数char tn[SIZE] = {0};bool over = false;    int w = n1[0];//截取位while(w != 0){d[1] = n1[w];plu(remd, d);while(cmp(remd, n2) == -1){//乘10之前保存个位余数if(w == 1){cpy(tn, remd);}mul(remd, ten);w--;//向右取之前确定可以取if(w == 0){over = true;break;}d[1] = n1[w];plu(remd, d);}if(over){break;}char qu = 0;//商while(cmp(remd, n2) != -1){qu++;sub(remd, n2);}//加在结果的当前截取到位plua(ans, w, qu);//乘10之前保存个位余数if(w == 1){cpy(tn, remd);}mul(remd, ten);w--;}cpy(remd, tn);//计算ans的位数    for(int i=n1[0]; i>=1; i--){        if(ans[i] != 0){            ans[0] = i;            break;        }    }    cpy(n1, ans);    cpy(q, remd);}/**********************************************/void plu(char* n1, char* n2){//加法,结果保存在n1int i;int k = 0;int maxlen = n1[0]>n2[0]?n1[0]:n2[0];for(i=1; i<=maxlen; i++){k = plua(n1, i, n2[i] + k);}n1[0] = maxlen;if(k){n1[0]++;n1[i] = k;}}int plua(char* n, int off, char num){//位加法,将n偏移为off的地方加上num,返回进位n[off] += num;if(n[off] > 9){int t = n[off]/10;n[off] %= 10;return t;}else{return 0;}}/**********************************************/int sub(char* n1, char* n2){    //减法,n1:被减数 n2:减数 n1>=n2 结果放在n1 返回1负数0正数    int foo;    char t[SIZE] = {0};    if((foo = cmp(n1, n2)) == -1){        cpy(t, n2);        cpy(n2, n1);        cpy(n1, t);    }    char w = 0;//借位数    int i=1;    for(;i<=n2[0]; i++){        w = suba(n1, i, n2[i] + w);    }    while(w){        w = suba(n1, i, n2[i] + w);        i++;    }    //清除无效0    for(int k=n1[0]; k>=1; k--){        if(n1[k] == 0){            n1[0]--;        }else{            break;        }    }    if(foo == -1){        //复原n2        cpy(n2, t);        return 1;    }else{        return 0;    }}int suba(char* n, int off, char num){//位减法,将n偏移为off的地方减去num,返回借位    n[off] -= num;    if(n[off] < 0){        n[off] += 10;        return 1;    }else{        return 0;    }}/**********************************************/

0 0