高精度整数运算改进版
2009-08-05 09:31
489 查看
/* Name: 高精度整数运算改进版 Copyright:始发于goal00001111的专栏;允许自由转载,但必须注明作者和出处 Author: goal00001111 Date: 15-12-08 08:18 Description: 高精度整数运算:加减乘除,乘方,阶乘 。 上次写了一个用字符串存储高精度整数的四则运算算法,虽然可以实现功能,但时间复杂度和空间复杂度都不够理想, 这次出了个改进版,将原来的用字符串存储改成用整型数组存储,而且改进了乘法,除法和乘方的算法,更快更高效! */ #include<iostream> #include<string> using namespace std; const unsigned int MAX = 10000; //整型数组的最大长度 const long long WIDTHMAX = 1000000000; //整型数组val[MAX]的元素上限 const unsigned int WIDTH = 9; //输出整型数组val[MAX]的元素时的格式宽度,即整型数组val[MAX]的元素的最多位数 typedef struct node { long long val[MAX]; //用来存储高精度整数 unsigned int size; //整型数组的实际长度 } BigInt; BigInt StrToBigInt(string s); void PrintBigInt(const BigInt & a); int ComPareBigInt(const BigInt & a, const BigInt & b); BigInt MulBigInt(const BigInt & a, const BigInt & b); BigInt AddBigInt(const BigInt & a, const BigInt & b); BigInt SubBigInt(BigInt a, BigInt b); BigInt DivBigInt(const BigInt & a, const BigInt & b); BigInt FacBigInt(unsigned int n); void PowBigInt(BigInt & c, const BigInt & a, unsigned int n); void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n); BigInt HalfBigInt(BigInt a); int main() { string s; BigInt a, b, c; cin >> s; a = StrToBigInt(s); cin >> s; b = StrToBigInt(s); cout << " "; PrintBigInt(a); cout << "+ "; PrintBigInt(b); c = AddBigInt(a, b); cout << "= "; PrintBigInt(c); cout << endl; cout << " "; PrintBigInt(a); cout << "- "; PrintBigInt(b); c = SubBigInt(a, b); cout << "= "; PrintBigInt(c); cout << endl; cout << " "; PrintBigInt(a); cout << "* "; PrintBigInt(b); c = MulBigInt(a, b); cout << "= "; PrintBigInt(c); cout << endl; cout << " "; PrintBigInt(a); cout << "/ 2 " << endl; c = HalfBigInt(a); cout << "= "; PrintBigInt(c); cout << endl; cout << " "; PrintBigInt(a); cout << "/ "; PrintBigInt(b); c = DivBigInt(a, b); cout << "= "; PrintBigInt(c); cout << endl; unsigned int n; cin >> n; //cout << n << "! = "; // c = FacBigInt(n); // PrintBigInt(c); // cout << c.size << endl; cout << endl; cout << " "; PrintBigInt(a); cout << "^" << n << " = "; PowBigInt(c, a, n); PrintBigInt(c); cout << endl; cout << " "; PrintBigInt(a); cout << "^" << n << " = "; PowBigInt_2(c, a, n); PrintBigInt(c); cout << endl; system("pause"); return 0; } /* 函数名称:PrintBigInt 函数功能:输出用整型数组表示的高精度整数 输入参数:const BigInt & a:用整型数组表示的高精度整数 输出参数:无 */ void PrintBigInt(const BigInt & a) { cout << a.val[a.size-1]; for (int i=a.size-2; i>=0; i--) { unsigned w = WIDTHMAX / 10; while (w > 0) { if (a.val[i] >= w) break; cout << 0; w /= 10; } cout << a.val[i]; } cout << endl; } /* 函数名称:StrToBigInt 函数功能:把元素为数字的字符串转换为用整型数组表示的高精度整数 输入参数:string s:存储数字的字符串 输出参数:BigInt:返回用整型数组表示的高精度整数 */ BigInt StrToBigInt(string s) { BigInt a; a.size = 0; int i = s.size(); unsigned long long sum = 0; while ( i>=WIDTH) { for (int j=i-WIDTH; j<i; j++) sum = sum * 10 + (s[j] - '0'); a.val[a.size++] = sum; sum = 0; i -= WIDTH; } if (i > 0) { for (int j=0; j<i; j++) sum = sum * 10 + (s[j] - '0'); a.val[a.size++] = sum; } return a; } /* 函数名称:AddBigInt 函数功能:高精度整数加法 输入参数:const BigInt & a:用整型数组表示的高精度整数加数 const BigInt & b:用整型数组表示的高精度整数加数 输出参数:BigInt:返回用整型数组表示的高精度整数和 */ BigInt AddBigInt(const BigInt & a, const BigInt & b) { //逆序计算a+b,则从低位开始计算 BigInt c; unsigned long long carry = 0; unsigned int i = 0; c.size = 0; while (i < a.size && i < b.size) { c.val[c.size++] = (a.val[i] + b.val[i] + carry) % WIDTHMAX; carry = (a.val[i] + b.val[i] + carry) / WIDTHMAX; i++; } while (i < a.size) { c.val[c.size++] = (a.val[i] + carry) % WIDTHMAX; carry = (a.val[i] + carry) / WIDTHMAX; i++; } while (i < b.size) { c.val[c.size++] = (b.val[i] + carry) % WIDTHMAX; carry = (b.val[i] + carry) / WIDTHMAX; i++; } if (carry > 0) c.val[c.size++] = carry; return c; } /* 函数名称:SubBigInt 函数功能:高精度整数减法 输入参数:BigInt a:用整型数组表示的高精度整数被减数 BigInt b:用整型数组表示的高精度整数减数 输出参数:BigInt:返回用整型数组表示的高精度整数差 */ BigInt SubBigInt(BigInt a, BigInt b) { BigInt c; c.size = 0; if (ComPareBigInt(a, b) == 0) { c.size = 1; c.val[0] = 0; return c; } bool flag = false; if (ComPareBigInt(a, b) < 0)//交换,并得到一个负号 { flag = true; BigInt temp = a; a = b; b = temp; } unsigned int i = 0; while (i < b.size) { if (a.val[i] >= b.val[i]) c.val[c.size++] = a.val[i] - b.val[i]; else { a.val[i+1] -= 1; c.val[c.size++] = a.val[i] + WIDTHMAX - b.val[i]; } i++; } while (i < a.size) { if (a.val[i] < 0) { a.val[i+1] -= 1; a.val[i] += WIDTHMAX; } c.val[c.size++] = a.val[i]; i++; } //消除多余的高位0 while (c.val[c.size-1] == 0) c.size--; if (flag)//如果是负数,加上负号 c.val[c.size-1] = -c.val[c.size-1]; return c; } /* 函数名称:ComPareBigInt 函数功能:比较两个高精度整数的大小 输入参数:BigInt a:用整型数组表示的高精度整数被减数 BigInt b:用整型数组表示的高精度整数减数 输出参数:int:a > b返回1,a = b返回0,a < b返回-1 */ int ComPareBigInt(const BigInt & a, const BigInt & b) { if (a.size > b.size) return 1; if (a.size < b.size) return -1; for (int i=a.size-1; i>=0; i--) { if (a.val[i] > b.val[i]) return 1; if (a.val[i] < b.val[i]) return -1; } return 0; } /* 函数名称:MulBigInt 函数功能:高精度整数乘法 输入参数:const BigInt & a:用整型数组表示的高精度整数被乘数 const BigInt & b:用整型数组表示的高精度整数乘数 输出参数:BigInt:返回用整型数组表示的高精度整数乘积 */ BigInt MulBigInt(const BigInt & a, const BigInt & b) { if (a.size == 1 && a.val[0] == 0) return a; if (b.size == 1 && b.val[0] == 0) return b; BigInt c; for (int i=0; i<MAX; i++) //全部赋初值为0 c.val[i] = 0; for (int i=0, j=0; i<b.size; i++) { for (j=0; j<a.size; j++) { c.val[i+j] += a.val[j] * b.val[i]; c.val[i+j+1] += c.val[i+j] / WIDTHMAX; c.val[i+j] %= WIDTHMAX; } c.size = i + j; if (c.val[c.size] != 0)//最高位有进位 c.size++; } return c; } /* 老版本: BigInt MulBigInt2(const BigInt & a, const BigInt & b) { if (a.size == 1 && a.val[0] == 0) return a; if (b.size == 1 && b.val[0] == 0) return b; BigInt c, tc; unsigned long long carry = 0; c.size = 0; for (int i=0, j=0; i<b.size; i++) { for (j=0; j<i; j++)//先在临时和tc的低位补足0 tc.val[j] = 0; carry = 0; for (j=0; j<a.size; j++) { tc.val[i+j] = (a.val[j] * b.val[i] + carry) % WIDTHMAX; carry = (a.val[j] * b.val[i] + carry) / WIDTHMAX; } tc.size = i + j; if (carry > 0) tc.val[tc.size++] = carry; //累加到c中 c = AddBigInt(tc, c); } return c; } */ /* 函数名称:FacBigInt 函数功能:高精度整数阶乘 输入参数:unsigned int n:正整数 输出参数:BigInt:返回用整型数组表示的高精度整数阶乘 */ BigInt FacBigInt(unsigned int n) { BigInt s, c; c.size = s.size = 1; s.val[0] = 1; for (unsigned long long i=2; i<=n; i++) { c.val[0] = i; s = MulBigInt(s, c); } return s; } /* 函数名称:PowBigInt 函数功能:递归高效算法求高精度整数幂 输入参数:BigInt & c:存储高精度整数幂的整型数组 const BigInt & a:用整型数组表示的高精度整数底数 long long n: 指数 */ void PowBigInt(BigInt & c, const BigInt & a, unsigned int n) { if (n == 1) { c = a; return ; } if (n == 0 || (a.size == 1 && a.val[0] == 1)) { c.size = c.val[0] = 1; return ; } PowBigInt(c, a, n/2); //递归求高精度整数幂 c = MulBigInt(c, c); //a^n = a^(n/2)*a^(n/2)*f(a) if (n % 2 == 1) //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1) c = MulBigInt(a, c); } /* 函数名称:PowBigInt_2 函数功能:非递归高效算法求高精度整数幂 输入参数:BigInt & c:存储高精度整数幂的整型数组 const BigInt & a:用整型数组表示的高精度整数底数 long long n: 指数 */ void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n) { int stack[MAX] = {0}; int top = 0; while (n > 0) //利用一个栈来存储n的状态:奇数还是偶数 { stack[top++] = n % 2; n /= 2; } c.size = c.val[0] = 1; for (int i=top-1; i>=0; i--) { c = MulBigInt(c, c); //a^n = a^(n/2)*a^(n/2)*f(a) if (stack[i] == 1) //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1) c = MulBigInt(a, c); } } /* 函数名称:DivBigInt 函数功能:二分法实现高精度整数除法 输入参数:const BigInt & a:用整型数组表示的高精度整数被除数 const BigInt & b:用整型数组表示的高精度整数除数 输出参数:BigInt:返回用整型数组表示的高精度整数商 */ BigInt DivBigInt(const BigInt & a, const BigInt & b) { BigInt high, low, mid, one, c; if ((a.size == 1 && a.val[0] == 0) || (b.size == 1 && b.val[0] == 0)) { c.size = 1; c.val[0] = 0; return c; } one.size = 1; //值为1的高精度整数 one.val[0] = 1; high = a; //上界 low.size = 1; //下界 low.val[0] = 0; while (ComPareBigInt(low, high) < 0) { mid = HalfBigInt(AddBigInt(high, low)); //中间数 c = MulBigInt(mid, b); if (ComPareBigInt(c, a) == 0) return mid; else if (ComPareBigInt(c, a) < 0) low = AddBigInt(mid, one); else high = SubBigInt(mid, one); } c = MulBigInt(low, b); if (ComPareBigInt(c, a) <= 0) return low; else return SubBigInt(low, one); } /* 函数名称:HalfBigInt 函数功能:高精度整数求半 输入参数:BigInt a:用整型数组表示的高精度整数 输出参数:BigInt:返回用整型数组表示的高精度整数的一半 */ BigInt HalfBigInt(BigInt a) { BigInt c; c.size = a.size; for (int i=a.size-1; i>0; i--) { c.val[i] = a.val[i] / 2; if (a.val[i] % 2 == 1) a.val[i-1] += WIDTHMAX; } c.val[0] = a.val[0] / 2; if (c.size > 0 && c.val[c.size-1] == 0) c.size--; return c; }
相关文章推荐
- 高精度整数运算改进版
- 高精度整数运算改进版(转)
- 高精度整数运算改进版
- 高精度整数运算
- 实用算法实现-第 24 篇 高精度整数运算
- 大整数运算(高精度运算)
- 实用算法实现-第 24 篇 高精度整数运算
- 高精度整数运算
- [算法设计与分析]3.2.4大整数存储及运算(高精度*长整数+n!)
- 正整数高精度运算
- 大整数运算||高精度运算
- 整数高精度运算的库(加法,减法,乘法,除法,取模)
- c语言高精度大整数加法运算
- 高精度运算总结(10.21更新整数乘法)
- 我的C实践(3):用宏和位运算来实现整数集合
- BZOJ 1263 SCOI 2006 整数划分 高精度
- 高精度运算(转)
- 如何判断除法运算结果是否为整数
- NYOJ 222 整数中的1 (二进制位运算,找规律)
- java中小数的处理:高精度运算用bigDecimal类,精度保留方法,即舍入方式的指定