/* *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 255 void 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复制为n2 for(int i=0; i<=n2[0]; i++){ n1[i] = n2[i]; } } /**********************************************/ void mul(char* n1, char* n2){ //乘法,结果保存在n1 char 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,完成进位,结果保存在n int 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最高位开始 余数=0 while(可以向右截取){ 余数 加上向右取的 while(取得的数小于n2){ 向右取 } while(余数 >= n2){ 商++ 余数 -= n2 } 商放在结果的 截取位的最右位 余数乘以10 } */ void div(char* n1, char* n2, char* q){ //除法,商保存在n1,余数保存在q char remd[SIZE] = {0};//余数 char ans[SIZE] = {0};//结果 char d[SIZE] = {0};//截取的一位数 d[0] = 1; char ten[SIZE] = {0};//长整数10 ten[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){ //加法,结果保存在n1 int 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; } } /**********************************************/
时间: 2024-10-13 16:16:57