一、大数相除
基本思路
大数除法是四则运算里面最难的一种。不同于一般的模拟,除法操作不是模仿手工除法,而是利用减法操作来实现的。其基本思想是反复做除法,看从被除数里面最多能减去多少个除数,商就是多少。逐个减显然太慢,要判断一次最多能减少多少个整数(除数)的10的n次方。
以7546除以23为例:
先用7546减去23的100倍,即减去2300,可以减3次,余下646,此时商就是300 (300=1003);
然后646减去23的10倍,即减去230,可以减2次,余下186,此时商就是320 (320=300+102);
然后186减去23,可以减8次,余下2,此时商就是328 (328=320+1*8);
因为2除以23的结果小于1,而我们又不用计算小数点位,所以不必再继续算下去了。
代码如下
#include <stdio.h> #include <string.h> #define MAXnumber 1000 int SubStract(int numdata1[], int num1size, int numdata2[], int num2size); int main() { char num1[MAXnumber] = {0}; //除数 char num2[MAXnumber] = {0}; //被除数 int numdata1[MAXnumber] = {0}; int numdata2[MAXnumber] = {0}; int result[MAXnumber] = {0}; //结果 int num1size,num2size; int dvalue; int nTemp; int i,j,x; //输入被除数与除数 scanf("%s",num1); num1size = strlen(num1); scanf("%s",num2); num2size = strlen(num2); //字符串倒序转化成数字,也就是个位数在0号位置 x = 0; for(i = num1size - 1; i >= 0; i--){ numdata1[x] = num1[i] - 48; x++; } x = 0; for(i = num2size - 1; i >= 0; i--){ numdata2[x] = num2[i] - 48; x++; } //将除数填充到与被除数相同的位数,也就是向右平移一个差值dvalue的位置。numdata2[i] = numdata2[i - dvalue]; //然后平移之后,其余数位填充为0.此时位数与被除数相同 dvalue = num1size - num2size; for(i = num1size - 1; i >= 0; i--){ if(i - dvalue >= 0){ numdata2[i] = numdata2[i - dvalue]; //将除数扩大,使得除数和被除数位数相等 } else{ numdata2[i] = 0; //其余填充为0 } } num2size = num1size; //更改被除数位数 //此步为关键步骤,重复调用,同时记录减成功的次数,即为商 //得到的商不可能大于差值,所以大范围循环是0-dvalue,目的是不断使对应的数位+1. //numdata2+i相当于除数向左移位,也就是去一个0;num2size - i表示被除数位数减一 //由于除法运算是不断的相减,所以当被除数不够减时,最高位为0,此时记录其位数nTemp,再反复循环 for(i = 0; i <= dvalue; i++){ while((nTemp = SubStract(numdata1, num1size, numdata2 + i, num2size - i)) >= 0 ){ num1size = nTemp; //结果长度 result[dvalue - i]++; //每成功减一次,将商的相应位加1 } } //输出商,逆向输出 printf("\n%s\n/\n%s\n=\n",num1,num2); for(i = dvalue; result[i] == 0; i--); for(; i >= 0; i--){ printf("%d",result[i]); } //输出余数 printf("\n余数为"); for(i = dvalue; numdata1[i] == 0; i--); for(; i >= 0; i--){ printf("%d",numdata1[i]); } return 0; } int SubStract(int numdata1[], int num1size, int numdata2[], int num2size) { int i; //判断能否满足减法运算 if(num1size < num2size){ return -1; } if(num1size == num2size){ for(i = num1size - 1; i >= 0; i--){ if(numdata1[i] > numdata2[i]){ break; } else if(numdata1[i] < numdata2[i]){ return -1; } } } //不够减借位 for(i = 0; i <= num1size - 1; i++){ numdata1[i] -= numdata2[i]; if(numdata1[i] < 0){ numdata1[i] += 10; numdata1[i+1]--; } } //查找结果的最高位,返回的是此时被除数的位数,两数相等时返回0. for(i = num1size - 1; i >= 0; i--){ if(numdata1[i]){ return (i+1); } } return 0; }
测试结果
二、大数相乘
基本思路
- 使用字符串对数据的输入
- 字符串倒序转换成数字
- 两个数组模仿乘法处理实现相乘,注意处理进位
- 消去多余的0
- 将结果翻转输出即为大数相乘的结果
代码如下
#include <stdio.h> #include <string.h> #define MAXnumber 1000 int main() { char firstnum[MAXnumber] = {0}; char secondnum[MAXnumber] = {0}; int firstnumdata[MAXnumber] = {0}; int secondnumdata[MAXnumber] = {0}; int resultdata[MAXnumber] = {0}; int firstsize,secondsize; int i,j,x; scanf("%s",firstnum); //输入第一个数据 firstsize = strlen(firstnum); scanf("%s",secondnum); //输入第二个数据 secondsize = strlen(secondnum); //字符串转换成数据 x = 0; for(i = firstsize - 1; i >= 0; i--){ firstnumdata[x] = firstnum[i] - 48; x++; } x = 0; for(i = secondsize - 1; i >= 0; i--){ secondnumdata[x] = secondnum[i] - 48; x++; } //大数相乘并处理好进位 for(j = 0; j < secondsize; j++){ for(i = 0; i < firstsize; i++){ resultdata[i+j] += firstnumdata[i]*secondnumdata[j]; } } for(i = 0; i < MAXnumber; i++){ if(resultdata[i] >= 10){ resultdata[i+1] += resultdata[i]/10; resultdata[i] = resultdata[i]%10; } } //翻转输出,并消除末尾多余的0 printf("%s*%s=",firstnum,secondnum); for(i = MAXnumber - 1; resultdata[i] == 0; i--); for(; i >= 0; i--){ printf("%d",resultdata[i]); } return 0; }
测试结果
三、大数相减
基本思路
方法相识,只是要做正负数的判断处理,同时不够减时向高位借位。
代码如下
#include <stdio.h> #include <string.h> #define MAXnumber 1000 int main() { char num1[MAXnumber] = {0}; char num2[MAXnumber] = {0}; int numdata1[MAXnumber] = {0}; int numdata2[MAXnumber] = {0}; int result[MAXnumber] = {0}; int num1size,num2size; int i,j,x; int flag = 1; //默认是正整数 scanf("%s",num1); num1size = strlen(num1); scanf("%s",num2); num2size = strlen(num2); //字符串转换成数据 x = 0; for(i = num1size - 1; i >= 0; i--){ numdata1[x] = num1[i] - 48; x++; } x = 0; for(i = num2size - 1; i >= 0; i--){ numdata2[x] = num2[i] - 48; x++; } //结果的正负号处理 if(num1size < num2size){ //长度不匹配,负数 flag = 0; } else if(num1size == num2size){ //从高位开始匹配每一位,若被减数较小,负数 for(x = num1size - 1; x >= 0; x--){ if(numdata1[x] == numdata2[x]){ continue; } else if(numdata1[x] < numdata2[x]){ flag = 0; break; } } } //减法处理,不够减向高位借位 if(flag){ for(i = 0; i < MAXnumber; i++){ if(numdata1[i] < numdata2[i]){ numdata1[i+1]--; result[i] = numdata1[i]+10-numdata2[i]; } else{ result[i] = numdata1[i]-numdata2[i]; } } } else{ for(i = 0; i < MAXnumber; i++){ if(numdata2[i] < numdata1[i]){ numdata2[i+1]--; result[i] = numdata2[i]+10-numdata1[i]; } else{ result[i] = numdata2[i]-numdata1[i]; } } } //结果翻转输出 printf("\n%s\n-\n%s\n=\n",num1,num2); if(flag == 0){ printf("-"); } for(i = MAXnumber - 1; result[i]==0; i--); for(; i >= 0; i--){ printf("%d",result[i]); } return 0; }
测试结果
四、大数相加
基本思路
同样是利用数组不断的进位,最后消0反转输出
代码如下
#include <stdio.h> #include <string.h> #define MAXnumber 1000 int main() { char num1[MAXnumber] = {0}; char num2[MAXnumber] = {0}; int numdata1[MAXnumber] = {0}; int numdata2[MAXnumber] = {0}; int result[MAXnumber] = {0}; int num1size,num2size; int i,j,x; scanf("%s",num1); num1size = strlen(num1); scanf("%s",num2); num2size = strlen(num2); x = 0; for(i = num1size - 1; i >= 0; i--){ numdata1[x] = num1[i] - 48; x++; } x = 0; for(i = num2size - 1; i >= 0; i--){ numdata2[x] = num2[i] - 48; x++; } for(i = 0; i < MAXnumber; i++){ result[i] = numdata1[i] + numdata2[i]; } for(i = 0; i < MAXnumber; i++){ if(result[i] >= 10){ result[i+1]++; result[i] = result[i] % 10; } } printf("\n%s\n+\n%s\n=\n",num1,num2); for(i = MAXnumber - 1; result[i]==0; i--); for(; i >= 0; i--){ printf("%d",result[i]); } return 0; }
测试结果