高效大数模板

  1 #include<iostream>
  2 #include<string>
  3 
  4 using namespace std;
  5 
  6 const unsigned int MAX = 10000; //整型数组的最大长度 
  7 const long long WIDTHMAX = 1000000000; //整型数组val[MAX]的元素上限 
  8 const unsigned int WIDTH = 9;  //输出整型数组val[MAX]的元素时的格式宽度,即整型数组val[MAX]的元素的最多位数 
  9 
 10 typedef struct node
 11 {
 12     long long val[MAX]; //用来存储高精度整数 
 13     unsigned int size; //整型数组的实际长度 
 14 } BigInt;
 15 
 16 BigInt StrToBigInt(string s);
 17 void PrintBigInt(const BigInt & a);
 18 int ComPareBigInt(const BigInt & a, const BigInt & b);
 19 BigInt MulBigInt(const BigInt & a, const BigInt & b);
 20 BigInt AddBigInt(const BigInt & a, const BigInt & b);
 21 BigInt SubBigInt(BigInt a, BigInt b);
 22 BigInt DivBigInt(const BigInt & a, const BigInt & b);
 23 BigInt FacBigInt(unsigned int n);
 24 void PowBigInt(BigInt & c, const BigInt & a, unsigned int n);
 25 void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n);
 26 BigInt HalfBigInt(BigInt a);
 27 
 28 int main()
 29 {
 30     string s;
 31     BigInt a, b, c;
 32     
 33     cin >> s;
 34     a = StrToBigInt(s);
 35     cin >> s;
 36     b = StrToBigInt(s);
 37     
 38     cout << "  ";
 39     PrintBigInt(a);
 40     cout << "+ ";
 41     PrintBigInt(b);
 42     c = AddBigInt(a, b);
 43     cout << "= ";
 44     PrintBigInt(c);
 45     cout << endl;
 46     
 47     cout << "  "; 
 48     PrintBigInt(a);
 49     cout << "- ";
 50     PrintBigInt(b);
 51     c = SubBigInt(a, b);
 52     cout << "= ";
 53     PrintBigInt(c);
 54     cout << endl;
 55     
 56     cout << "  ";
 57     PrintBigInt(a);
 58     cout << "* ";
 59     PrintBigInt(b);
 60     c = MulBigInt(a, b);
 61     cout << "= ";
 62     PrintBigInt(c);
 63     cout << endl;
 64     
 65     cout << "  ";
 66     PrintBigInt(a);
 67     cout << "/ 2 " << endl;
 68     c = HalfBigInt(a);
 69     cout << "= ";
 70     PrintBigInt(c);
 71     cout << endl;
 72     
 73     cout << "  ";
 74     PrintBigInt(a);
 75     cout << "/ ";
 76     PrintBigInt(b);
 77     c = DivBigInt(a, b);
 78     cout << "= ";
 79     PrintBigInt(c);
 80     cout << endl;
 81     
 82     unsigned int n;
 83     cin >> n;
 84     //cout << n << "! = ";
 85 //    c = FacBigInt(n);
 86 //    PrintBigInt(c);
 87 //    cout << c.size << endl;
 88      cout << endl;
 89 
 90     cout << "  ";
 91     PrintBigInt(a);
 92     cout << "^" << n << " = ";
 93     PowBigInt(c, a, n);
 94     PrintBigInt(c);
 95     cout << endl;
 96     
 97     cout << "  ";
 98     PrintBigInt(a);
 99     cout << "^" << n << " = ";
100     PowBigInt_2(c, a, n);
101     PrintBigInt(c);
102     cout << endl;
103     
104     system("pause");
105     return 0;
106 }
107 /*
108 函数名称:PrintBigInt
109 函数功能:输出用整型数组表示的高精度整数
110 输入参数:const BigInt & a:用整型数组表示的高精度整数
111 输出参数:无
112 */
113 void PrintBigInt(const BigInt & a)
114 {
115     cout << a.val[a.size-1];
116     for (int i=a.size-2; i>=0; i--)
117     {
118         unsigned w = WIDTHMAX / 10;
119         while (w > 0)
120         {
121             if (a.val[i] >= w)
122                 break;
123             cout << 0;
124             w /= 10;
125         }
126         cout << a.val[i];
127     }
128     cout << endl; 
129 }
130 /*
131 函数名称:StrToBigInt
132 函数功能:把元素为数字的字符串转换为用整型数组表示的高精度整数
133 输入参数:string s:存储数字的字符串 
134 输出参数:BigInt:返回用整型数组表示的高精度整数
135 */
136 BigInt StrToBigInt(string s)
137 {
138     BigInt a;
139     a.size = 0;
140     int i = s.size();
141     unsigned long long sum = 0;
142     while ( i>=WIDTH)
143     {
144         for (int j=i-WIDTH; j<i; j++)
145             sum = sum * 10 + (s[j] - '0');
146         a.val[a.size++] = sum;
147         sum = 0;
148         i -= WIDTH;
149     } 
150     if (i > 0)
151     {
152         for (int j=0; j<i; j++)
153             sum = sum * 10 + (s[j] - '0');
154         a.val[a.size++] = sum;
155     } 
156     return a;
157 }
158 /*
159 函数名称:AddBigInt
160 函数功能:高精度整数加法
161 输入参数:const BigInt & a:用整型数组表示的高精度整数加数 
162           const BigInt & b:用整型数组表示的高精度整数加数 
163 输出参数:BigInt:返回用整型数组表示的高精度整数和 
164 */
165 BigInt AddBigInt(const BigInt & a, const BigInt & b)
166 {
167     //逆序计算a+b,则从低位开始计算 
168     BigInt c;
169     unsigned long long carry = 0;
170     unsigned int i = 0;
171     c.size = 0;
172     while (i < a.size && i < b.size)
173     {
174         c.val[c.size++] = (a.val[i] + b.val[i] + carry) % WIDTHMAX; 
175         carry = (a.val[i] + b.val[i] + carry) / WIDTHMAX; 
176         i++;
177     }
178     while (i < a.size)
179     {
180         c.val[c.size++] =  (a.val[i] + carry) % WIDTHMAX; 
181         carry = (a.val[i] + carry) / WIDTHMAX; 
182         i++;
183     }
184     while (i < b.size)
185     {
186         c.val[c.size++] =  (b.val[i] + carry) % WIDTHMAX; 
187         carry = (b.val[i] + carry) / WIDTHMAX; 
188         i++;
189     }
190     if (carry > 0)
191         c.val[c.size++] = carry; 
192     return c;
193 }
194 /*
195 函数名称:SubBigInt
196 函数功能:高精度整数减法
197 输入参数:BigInt a:用整型数组表示的高精度整数被减数 
198           BigInt b:用整型数组表示的高精度整数减数 
199 输出参数:BigInt:返回用整型数组表示的高精度整数差 
200 */
201 BigInt SubBigInt(BigInt a, BigInt b)
202 {
203     BigInt c;
204     c.size = 0;
205     if (ComPareBigInt(a, b) == 0)
206     {
207         c.size = 1;
208         c.val[0] = 0;
209         return c; 
210     }
211     bool flag = false;
212     if (ComPareBigInt(a, b) < 0)//交换,并得到一个负号 
213     {
214         flag = true;
215         BigInt temp = a;
216         a = b;
217         b = temp;
218     }
219     unsigned int i = 0;
220     while (i < b.size)
221     {
222         if (a.val[i] >= b.val[i])
223              c.val[c.size++] = a.val[i] - b.val[i];
224         else
225         {
226             a.val[i+1] -= 1;
227             c.val[c.size++] = a.val[i] + WIDTHMAX - b.val[i];
228         }   
229         i++;
230     }
231     while (i < a.size)
232     {
233         if (a.val[i] < 0)
234         {
235             a.val[i+1] -= 1;
236             a.val[i] += WIDTHMAX;
237         }
238         c.val[c.size++] = a.val[i];
239         i++;
240     }
241     //消除多余的高位0
242     while (c.val[c.size-1] == 0) 
243         c.size--;
244            
245     if (flag)//如果是负数,加上负号 
246         c.val[c.size-1] = -c.val[c.size-1];
247     return c;
248 }
249 /*
250 函数名称:ComPareBigInt
251 函数功能:比较两个高精度整数的大小 
252 输入参数:BigInt a:用整型数组表示的高精度整数被减数 
253           BigInt b:用整型数组表示的高精度整数减数 
254 输出参数:int:a > b返回1,a = b返回0,a < b返回-1
255 */
256 int ComPareBigInt(const BigInt & a, const BigInt & b)
257 {
258     if (a.size > b.size)
259         return 1;
260     if (a.size < b.size)
261         return -1;
262         
263     for (int i=a.size-1; i>=0; i--) 
264     {
265         if (a.val[i] > b.val[i])
266             return 1;
267         if (a.val[i] < b.val[i])
268             return -1;
269     }
270     return 0;
271 }
272 /*
273 函数名称:MulBigInt
274 函数功能:高精度整数乘法
275 输入参数:const BigInt & a:用整型数组表示的高精度整数被乘数 
276           const BigInt & b:用整型数组表示的高精度整数乘数 
277 输出参数:BigInt:返回用整型数组表示的高精度整数乘积 
278 */
279 BigInt MulBigInt(const BigInt & a, const BigInt & b)
280 {
281     if (a.size == 1 && a.val[0] == 0)
282         return a;
283     if (b.size == 1 && b.val[0] == 0)
284         return b;
285  
286     BigInt c;
287     for (int i=0; i<MAX; i++) //全部赋初值为0 
288         c.val[i] = 0;
289     for (int i=0, j=0; i<b.size; i++)
290     {
291         for (j=0; j<a.size; j++)
292         {
293             c.val[i+j] += a.val[j] * b.val[i]; 
294             c.val[i+j+1] += c.val[i+j] / WIDTHMAX; 
295             c.val[i+j] %= WIDTHMAX; 
296         }
297         c.size = i + j;
298         if (c.val[c.size] != 0)//最高位有进位 
299             c.size++;
300     }
301     return c;
302 }
303 /*
304 老版本: 
305 BigInt MulBigInt2(const BigInt & a, const BigInt & b)
306 {
307     if (a.size == 1 && a.val[0] == 0)
308         return a;
309     if (b.size == 1 && b.val[0] == 0)
310         return b;
311  
312     BigInt c, tc;
313     unsigned long long carry = 0;
314     c.size = 0;
315     for (int i=0, j=0; i<b.size; i++)
316     {
317         for (j=0; j<i; j++)//先在临时和tc的低位补足0 
318             tc.val[j] = 0;
319         carry = 0;
320         for (j=0; j<a.size; j++)
321         {
322             tc.val[i+j] = (a.val[j] * b.val[i] + carry) % WIDTHMAX; 
323             carry = (a.val[j] * b.val[i] + carry) / WIDTHMAX; 
324         }
325         tc.size = i + j;
326         if (carry > 0)
327             tc.val[tc.size++] = carry; 
328         //累加到c中 
329         c = AddBigInt(tc, c);
330     }
331     return c;
332 }
333 */
334 
335 /*
336 函数名称:FacBigInt
337 函数功能:高精度整数阶乘
338 输入参数:unsigned int n:正整数 
339 输出参数:BigInt:返回用整型数组表示的高精度整数阶乘 
340 */
341 BigInt FacBigInt(unsigned int n)
342 {
343     BigInt s, c;
344     c.size = s.size = 1;
345     s.val[0] = 1;
346     for (unsigned long long i=2; i<=n; i++)
347     {
348         c.val[0] = i;
349         s = MulBigInt(s, c);
350     }
351     return s;
352 }
353 
354 /*
355 函数名称:PowBigInt
356 函数功能:递归高效算法求高精度整数幂
357 输入参数:BigInt & c:存储高精度整数幂的整型数组 
358           const BigInt & a:用整型数组表示的高精度整数底数 
359           long long n:  指数
360 */
361 void PowBigInt(BigInt & c, const BigInt & a, unsigned int n)
362 {
363     if (n == 1)
364     {
365         c = a;
366         return ;
367     }
368     if (n == 0 || (a.size == 1 && a.val[0] == 1))
369     {
370         c.size = c.val[0] = 1;
371         return ;  
372     }
373     
374     PowBigInt(c, a, n/2); //递归求高精度整数幂 
375     
376     c = MulBigInt(c, c); //a^n = a^(n/2)*a^(n/2)*f(a)
377     if (n % 2 == 1)      //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)
378         c = MulBigInt(a, c);
379 }
380 
381 /*
382 函数名称:PowBigInt_2
383 函数功能:非递归高效算法求高精度整数幂
384 输入参数:BigInt & c:存储高精度整数幂的整型数组 
385           const BigInt & a:用整型数组表示的高精度整数底数 
386           long long n:  指数
387 */
388 void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n)
389 {
390     int stack[MAX] = {0};
391     int top = 0;
392     while (n > 0) //利用一个栈来存储n的状态:奇数还是偶数 
393     {
394         stack[top++] = n % 2;
395         n /= 2;
396     }
397     c.size = c.val[0] = 1;
398     for (int i=top-1; i>=0; i--)
399     {
400         c = MulBigInt(c, c);  //a^n = a^(n/2)*a^(n/2)*f(a)
401         if (stack[i] == 1)   //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)
402             c = MulBigInt(a, c);
403     }
404 }
405 
406 /*
407 函数名称:DivBigInt
408 函数功能:二分法实现高精度整数除法
409 输入参数:const BigInt & a:用整型数组表示的高精度整数被除数 
410           const BigInt & b:用整型数组表示的高精度整数除数 
411 输出参数:BigInt:返回用整型数组表示的高精度整数商 
412 */
413 BigInt DivBigInt(const BigInt & a, const BigInt & b)
414 {
415     BigInt high, low, mid, one, c;
416     if ((a.size == 1 && a.val[0] == 0) || (b.size == 1 && b.val[0] == 0))
417     {
418         c.size = 1;
419         c.val[0] = 0;
420         return c;
421     }
422     
423     one.size = 1; //值为1的高精度整数 
424     one.val[0] = 1;
425     high = a;  //上界 
426     low.size = 1; //下界 
427     low.val[0] = 0;
428     while (ComPareBigInt(low, high) < 0)
429     {
430         mid = HalfBigInt(AddBigInt(high, low)); //中间数 
431         c = MulBigInt(mid, b);
432         if (ComPareBigInt(c, a) == 0)
433             return mid;
434         else if (ComPareBigInt(c, a) < 0)
435             low = AddBigInt(mid, one);
436         else 
437             high = SubBigInt(mid, one);
438     }      
439     c = MulBigInt(low, b);
440     if (ComPareBigInt(c, a) <= 0)
441         return low;
442     else 
443         return SubBigInt(low, one);
444 }
445 
446 /*
447 函数名称:HalfBigInt
448 函数功能:高精度整数求半 
449 输入参数:BigInt a:用整型数组表示的高精度整数
450 输出参数:BigInt:返回用整型数组表示的高精度整数的一半 
451 */
452 BigInt HalfBigInt(BigInt a)
453 {
454     BigInt c;
455     c.size = a.size;
456     for (int i=a.size-1; i>0; i--)
457     {
458         c.val[i] = a.val[i] / 2;   
459         if (a.val[i] % 2 == 1)
460             a.val[i-1] += WIDTHMAX;
461     }
462     c.val[0] = a.val[0] / 2;   
463     if (c.size > 0 && c.val[c.size-1] == 0)
464         c.size--;
465         
466     return c;
467 }
View Code

 

转载于:https://www.cnblogs.com/Skyxj/p/3185064.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值