大整数的加减乘除
多项式的加减乘除能够利用多项式的加减乘除进行运算,所以下面程序採用了多项式的加减乘除。多项式运算已经在《算法导论》第30章有简要的介绍,详细的请參考数学书。
大整数加法:(利用书上公式轻松得出)
//多项式加法-大数加法 #include <iostream> #include <time.h> using namespace std; #define m1 4 #define m2 5 //a[0]=x^0 a[1]=x^1....a[n]=x^n的关于x的多项式系数 //b[0]=x^0 b[1]=x^1....b[n]=x^n表示还有一关于x的多项式系数 //多项式的系数也能够看做每位上的数字 const int k=m1<m2?m2:m1; void Simple_Large_int_add(int a[],int b[],int c[]) { for (int i=0;i<=k;i++) { c[i]+=a[i]+b[i]; if (c[i]>=10) { c[i+1]=c[i]/10; c[i]%=10; } } } void main() { srand( (unsigned)time( NULL ) ); int a[k+1]={4,2,5,1,7};//12345X12345=152399025 int b[k+1]={6,2,1,4,0,0}; int c[k+1]={0}; for (int i=m1;i>=0;i--) { //a[i]=rand()%10; cout<<a[i]; } cout<<" + "; for ( i=m2;i>=0;i--) { //b[i]=rand()%10; cout<<b[i]; } cout<<"="; Simple_Large_int_add(a,b,c); for ( i=k;i>=0;i--) { if (i==k&&c[i]==0) { continue; } cout<<c[i]; } cout<<endl; }
大整数减法:(和加法类似)
//多项式减法-大数减法 #include <iostream> #include <time.h> using namespace std; #define m1 1000 #define m2 898 //a[0]=x^0 a[1]=x^1....a[n]=x^n的关于x的多项式系数 //b[0]=x^0 b[1]=x^1....b[n]=x^n表示还有一关于x的多项式系数 //多项式的系数也能够看做每位上的数字 const int k=m1<m2?m2:m1; void Simple_Large_int_Sub(int a[],int b[],int c[]) { for (int i=0;i<=k;i++) { if (k==m1) { if (a[i]<b[i]) { c[i]+=a[i]+10-b[i]; a[i+1]=a[i+1]-1; } else c[i]+=a[i]-b[i]; } else { if (b[i]<a[i]) { c[i]+=b[i]+10-a[i]; b[i+1]=b[i+1]-1; } else c[i]+=b[i]-a[i]; } } } void main() { srand( (unsigned)time( NULL ) ); int a[k+1]={0};//12345X12345=152399025 int b[k+1]={0}; int c[k+1]={0}; for (int i=m1;i>=0;i--) { a[i]=rand()%10; cout<<a[i]; } cout<<" - "; for ( i=m2;i>=0;i--) { b[i]=rand()%10; cout<<b[i]; } cout<<" = "; Simple_Large_int_Sub(a,b,c); int temp=k; if (k==m2) { temp=k; c[temp]=-c[temp]; while (c[temp]==0) { --temp; c[temp]=-c[temp]; if (c[temp]!=0) { break; } } } for ( i=temp;i>=0;i--) { cout<<c[i]; } cout<<endl; }
大整数的乘法:(利用书上的公式轻松得出)
//多项式乘法-大数乘法 #include <iostream> #include <time.h> using namespace std; #define m1 300 #define m2 400 #define n m1+m2 //a[0]=x^0 a[1]=x^1....a[n]=x^n的关于x的多项式系数 //b[0]=x^0 b[1]=x^1....b[n]=x^n表示还有一关于x的多项式系数 //多项式的系数也能够看做每位上的数字 void Simple_Large_int_multiplication(int a[],int b[],int c[]) { for (int j=n-1;j>=0;j--) { int i=n-1-j; for (int k=0;k<=j;k++) { c[i]+=a[k]*b[j-k]; } if (c[i]>=10) { c[i+1]=c[i]/10; c[i]%=10; } } } void main() { srand( (unsigned)time( NULL ) ); int a[n+1]={0};//12345X12345=152399025 int b[n+1]={0}; int c[n+1]={0}; for (int i=0;i<m1;i++) { a[i]=rand()%10; cout<<a[i]; } cout<<" X "; for ( i=0;i<m2;i++) { b[i]=rand()%10; cout<<b[i]; } cout<<" = "; Simple_Large_int_multiplication(a,b,c); for ( i=n;i>0;i--) { if (i==n&&c[i]==0) { continue; } cout<<c[i]; } cout<<endl; }
大整数的除法:(能够由大整数减法得出,算是比較复杂的一个四则运算了)
參考资料:超大整数除法 可是这个链接里的代码有3点须要说明:1,当被除数与除数同样时,会产生错误,比方701/101返回的是1,而不是6. 2,这个代码用了string数组,我和他不太一样,我用的是int数组,所以代码还是有差别的。3,另一点须要说明,他的代码用了 itoa系统函数,这个函数在VS2013编译器已经被废弃了。
//*************************超长整数除法*******************************/ //*核心思想是程序中使用了int数组存放大整数的每一位,扩大除数的倍数使其*/ //*位数与被除数位数同样,然后被除数与除数每循环一次,就比較一次。*****/ //*假设被除数<除数,不进行大整数的减法,除数降低1位继续下一次循环****/ //*假设被除数>除数,进入大整数的循环减法操作直到被除数小于除数,*****/ //*而后相同进行下一层循环。这样经过数次循环直到被扩大倍数的除数位*****/ //*数降低到初始除数位数为止这样能够同一时候得到余数和商完毕大整数除法操作*/ //*比如10480÷45扩大100倍=>10480÷45000降低1位=>10480÷4500发现能减2次/ //*1048÷4500缩小1位=>1048÷450发现能减3次=>130÷450降低1位=>130÷45**/ //*发现能减2次=>40÷45除数为初始除数循环结束,除法结束 终于余数40商232/ //*这除法执行时间是对于β位的大整数须要O(β^2)时间********************/ #include <iostream> #include <time.h> using namespace std; #define m1 500 #define m2 150 //a[0]=x^0 a[1]=x^1....a[n]=x^n的关于x的多项式系数 //b[0]=x^0 b[1]=x^1....b[n]=x^n表示还有一关于x的多项式系数 //多项式的系数也能够看做每位上的数字 const int k = m1<m2 ? m2 : m1; int len1 = m1, len2 = m2; //被除数大于除数的辅助大整数减法函数 void help1(int a[], int b[], int c[])//O(β) 对于β位整数来说 { int j = k; while (j >= 0)c[j--] = 0; for (int i = 0; i <= k; i++) { if (a[i]<b[i]) { c[i] += a[i] + 10 - b[i]; a[i + 1] = a[i + 1] - 1; } else c[i] += a[i] - b[i]; a[i] = c[i]; } while (!a[len1]) --len1; } //大整数的减法 int Simple_Large_int_Sub(int a[], int b[], int c[])//O(β) 对于β位整数来说 { if (len1 == len2) { int i = len1; while (a[i] == b[i]) i--; if (a[i]>b[i]) { help1(a, b, c); return 1; } else return -1; } else { if (len2<len1) { help1(a, b, c); return 1; } else return -1; } } int divide(int a[], int b[], int c[]) { int res[k + 1] = { 0 }, temp = 0, flag = 0;//res数组是存放商的数组 if (len2 == 0 && b[0] == 0) { cout << "除数不能为0!" << endl; return 0; } if (len1<len2) { return 1; } else { if (len1 == len2) { int i = len1; while (a[i] == b[i])i--; if (a[i] < b[i])return 1; } while (!b[len2])len2--;//00xxx...化简为xxx,第一个非0数字之前的所有0所有去掉后计算大整数的实际位数 while (!a[len1])len1--;//同上,假设不进行随机生成大整数的话,那么这两个循环能够省略掉 int p = len1 - len2; int j = len2, q = len2; int i = (len2 += p); while (i >= 0)//这个循环是给除数末尾补0使其与被除数位数一样, { if (j<0) { b[i--] = 0; continue; } b[i] = b[j]; --i; --j; } while (p >= 0)//O(cβ^2) {//O(β1-β2)=O(β)最外层循环运行次数就是2个整数的差值,最大可能到β位(由于β位-1位=β位) int t = 0; int q2 = len2;//q2至少为1 while (Simple_Large_int_Sub(a, b, c) >= 0)//O(cβ)每次计算大整数相减,都要进行β次循环 t++;//t<10=>O(c) 最多循环9次,所以这层循环仅仅需花费常数时间 res[p] = t; if (res[p] != 0 && flag == 0){ temp = p; flag = 1; } p--; //len2--; int i = 0; q2 -= len1;//计算len2降低的实际位数 if (q2 == 0)q2 = 1; len2 -= q2; while (i <= k&&len2>q - 1) { if (i>len2) { b[i++] = 0; continue; } b[i] = b[i + q2]; i++; } if (len2 <= q - 1){ break; }//假设经过X10加倍的除数降低到小于等于原来的除数-1,那么除法结束跳出循环 while (q2>1)//假设q2降低的位数超过1位,那么须要给商补0 { res[p--] = 0; q2--; } } cout << "商="; for (j = temp; j >= 0; j--) { cout << res[j]; } return 2; }//除数长度大于被除数长度 } void main() { srand((unsigned)time(NULL)); int a[k + 1] = { 0 }; int b[k + 1] = { 0 }; int c[k + 1] = { 0 };//c为暂时数组 for (int i = m1; i >= 0; i--) { a[i]=rand()%10; cout << a[i]; } cout << " ÷ "; for ( i = m2; i >= 0; i--) { b[i] = rand() % 10; cout << b[i]; } cout << " = "; int p = divide(a, b, c); if (p == 1) { cout << "商=" << "0" << endl; cout << "余数="; for (int i = m1; i >= 0; i--) { cout << a[i]; } } else if (p == 2) { cout << "余数="; int i = k; while (!a[i]&&i!=0)--i; for (int j = i; j >= 0; j--) { cout << a[j]; } } else cout << "输入错误!" << endl; cout << endl; }