大数运算产生的原因就是因为int,double类型表示范围都有限,无法表示过长的数字比如:2345468454567865415467864453437。
因此也就无法进行四则运算,为了实现这种运算,大数运算产生了。
其实也很简单,既然基本数据类型放不下这些数据,那就用数组存放呗。
定义char c[100000000],总能放下这么大的数了吧,当然因为这些数是用数组保存的,那么对它们进行运算也就不能简单的加减乘除了。只能通过模拟人工计算的方法来实现。
大数运算最难的在于除法的运算,其他的加减乘都是模拟人的计算方法。
如果模拟人工的计算方法来计算除法,emm....怎么模拟,貌似不太简单。
所以除法就是将除法转换为减法来运算。 例如计算6/2,可以转换为计算6-2能减多少次,很显然,能减三次,所以答案就出来了。为3。
废话不多说 上代码。
#include<stdio.h> #include<string.h> #define max(a,b) (a>b?a:b) //比较两个字符串数值,前者大返回正数,相等返回0,前者小负数; int compare(char *a,char *b) { if(strlen(a)>strlen(b)) return 1; else if(strlen(a)<strlen(b)) return -1; else return strcmp(a,b); } void add(char *a,char *b,char *num)//加法 { int flag; int j1=0; char num1[100000]= {0},num2[100000]= {0}; /* 逆序存放a,b 且将ascll码转为0-9*/ for(int i=strlen(a)-1,j=0; i>=0; i--,j++) num1[i]=a[j]-48; for(int i=strlen(b)-1,j=0; i>=0; i--,j++) num2[i]=b[j]-48; for(int i=0; i<max(strlen(a),strlen(b))+1; i++) if(num1[i]+num2[i]>9)//相加>9,向高位进位 { num1[i+1]++; num1[i]=num1[i]+num2[i]-10; } else num1[i]+=num2[i]; for(flag=99999; num1[flag]==0; flag--); for(int i=flag; i>=0; i--,j1++)//将结果转回正序,且转换回ascll码 { num[j1]=num1[i]+48; } num[j1]='\0'; } void sub(char *a,char *b,char *num)//减法 { int flag; int j1=0; char num1[100000]= {0},num2[100000]= {0}; //如果a<b,将a b互换,并且输出负号 if(compare(a,b)<0) { printf("-"); //同加法 for(int i=strlen(b)-1,j=0; i>=0; i--,j++) num1[i]=b[j]-48; for(int i=strlen(a)-1,j=0; i>=0; i--,j++) num2[i]=a[j]-48; } else { for(int i=strlen(a)-1,j=0; i>=0; i--,j++) num1[i]=a[j]-48; for(int i=strlen(b)-1,j=0; i>=0; i--,j++) num2[i]=b[j]-48; } for(int i=0; i<strlen(a); i++) { if(num1[i]-num2[i]<0)//<0,向高位借位 { num1[i+1]--; num1[i]=num1[i]-num2[i]+10; } else num1[i]-=num2[i]; } for(flag=99999; num1[flag]==0&&flag>0; flag--); if(compare(a,b)<0) num[j1]='-',j1++; for(int i=flag; i>=0; i--,j1++) { num[j1]=num1[i]+48; } num[j1]='\0'; } void mul(char *a,char *b,char *num)//乘法 { int flag; int j1=0; char mu=0,ad=0;//mu积进位,ad和进位 char result[200000]= {0}; char num1[100000]= {0},num2[100000]= {0}; /* 逆序存放a,b 同加法*/ for(int i=strlen(a)-1,j=0; i>=0; i--,j++) num1[i]=a[j]-48; for(int i=strlen(b)-1,j=0; i>=0; i--,j++) num2[i]=b[j]-48; /*核心部分 *将已有result[i+j]与当前计算出的result[i+j]相加,并且和 进位 *计算当前result[i+j],并且记录积进位,!!!!注意:积进位不能直接进位,要先记录下,下次计算再进位。 *模拟人工乘法 */ for(int i=0; i<strlen(a)+1; i++) for(int j=0; j<strlen(b)+1; j++) { flag=num1[i]*num2[j]+mu; mu=flag/10; if(result[i+j]+flag%10>9) { result[i+j+1]++; result[i+j]=result[i+j]+flag%10-10; } else result[i+j]=result[i+j]+flag%10; } for(flag=99999; result[flag]==0&&flag>0; flag--); for(int i=flag; i>=0; i--,j1++) { num[j1]=result[i]+48; } num[j1]='\0'; } /* 大数除法原理:反复做减法,看从被除数里面最多能减去多少个除数,商就是多少。 逐个减显然太慢,要判断一次最多能减少多少个整的10的n次方。 以7546除23为例。 先减去23的100倍,就是2300,可以减3次,余下646。 此时商就是300; 然后646减去23的10倍,就是230,可以减2次,余下186。此时商就是320; 然后186减去23,可以减8次,此时商就是328. */ void div(char *a,char *b,char *num)//除法 { if(compare(a,b)<0)//a<b { num[0]='0'; num[1]='\0'; } else if(compare(a,b)==0)//a==b { num[0]='1'; num[1]='\0'; } else //a>b { int j=0; memset(num,48,200000);//20000为数组大小 char num1[100000]= {0},num2[100000]= {0}; strcpy(num1,a); int alength=strlen(a),blength=strlen(b); int divalue=alength-blength;//两个数据相差的位数 while(divalue>=0) { int i=0; strcpy(num2,b); num2[blength+divalue]='\0'; //将b放大为与a位数相同 for( ;i<divalue; i++) num2[blength+i]='0'; while(compare(num1,num2)>=0) //a b相减 直到a<b { sub(num1,num2,num1); num[j]++; } divalue--; j++; } num[j]='\0'; if(num[0]==48)//去除首位的0 strcpy(num,num+1); } } int main() { char a[100000],b[100000],result[200000]; scanf("%s%s",a,b); add(a,b,result); printf("\n+:%s",result); sub(a,b,result); printf("\n-:%s",result); mul(a,b,result); printf("\n*:%s",result); div(a,b,result); printf("\n/:%s",result); return 0; }