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

/*
*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;
    }
}
/**********************************************/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值