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