Chinaunix首页 | 论坛 | 博客
  • 博客访问: 614539
  • 博文数量: 113
  • 博客积分: 2554
  • 博客等级: 少校
  • 技术积分: 1428
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-21 19:53
文章分类

全部博文(113)

文章存档

2014年(1)

2013年(2)

2012年(94)

2011年(16)

分类: LINUX

2012-03-06 14:48:37

  1. /*
  2.   Name: 高精度整数运算改进版
  3.   Copyright:始发于goal00001111的专栏;允许自由转载,但必须注明作者和出处
  4.   Author: goal00001111
  5.   Date: 15-12-08 08:18
  6.   Description:
  7. 高精度整数运算:加减乘除,乘方,阶乘 。
  8. 上次写了一个用字符串存储高精度整数的四则运算算法,虽然可以实现功能,但时间复杂度和空间复杂度都不够理想,
  9. 这次出了个改进版,将原来的用字符串存储改成用整型数组存储,而且改进了乘法,除法和乘方的算法,更快更高效!
  10. */
  11. #include<iostream>
  12. #include<string>

  13. using namespace std;

  14. const unsigned int MAX = 10000; //整型数组的最大长度
  15. const long long WIDTHMAX = 1000000000; //整型数组val[MAX]的元素上限
  16. const unsigned int WIDTH = 9; //输出整型数组val[MAX]的元素时的格式宽度,即整型数组val[MAX]的元素的最多位数

  17. typedef struct node
  18. {
  19.     long long val[MAX]; //用来存储高精度整数
  20.     unsigned int size; //整型数组的实际长度
  21. } BigInt;

  22. BigInt StrToBigInt(string s);
  23. void PrintBigInt(const BigInt & a);
  24. int ComPareBigInt(const BigInt & a, const BigInt & b);
  25. BigInt MulBigInt(const BigInt & a, const BigInt & b);
  26. BigInt AddBigInt(const BigInt & a, const BigInt & b);
  27. BigInt SubBigInt(BigInt a, BigInt b);
  28. BigInt DivBigInt(const BigInt & a, const BigInt & b);
  29. BigInt FacBigInt(unsigned int n);
  30. void PowBigInt(BigInt & c, const BigInt & a, unsigned int n);
  31. void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n);
  32. BigInt HalfBigInt(BigInt a);

  33. int main()
  34. {
  35.     string s;
  36.     BigInt a, b, c;
  37.     
  38.     cin >> s;
  39.     a = StrToBigInt(s);
  40.     cin >> s;
  41.     b = StrToBigInt(s);
  42.     
  43.     cout << " ";
  44.     PrintBigInt(a);
  45.     cout << "+ ";
  46.     PrintBigInt(b);
  47.     c = AddBigInt(a, b);
  48.     cout << "= ";
  49.     PrintBigInt(c);
  50.     cout << endl;
  51.     
  52.     cout << " ";
  53.     PrintBigInt(a);
  54.     cout << "- ";
  55.     PrintBigInt(b);
  56.     c = SubBigInt(a, b);
  57.     cout << "= ";
  58.     PrintBigInt(c);
  59.     cout << endl;
  60.     
  61.     cout << " ";
  62.     PrintBigInt(a);
  63.     cout << "* ";
  64.     PrintBigInt(b);
  65.     c = MulBigInt(a, b);
  66.     cout << "= ";
  67.     PrintBigInt(c);
  68.     cout << endl;
  69.     
  70.     cout << " ";
  71.     PrintBigInt(a);
  72.     cout << "/ 2 " << endl;
  73.     c = HalfBigInt(a);
  74.     cout << "= ";
  75.     PrintBigInt(c);
  76.     cout << endl;
  77.     
  78.     cout << " ";
  79.     PrintBigInt(a);
  80.     cout << "/ ";
  81.     PrintBigInt(b);
  82.     c = DivBigInt(a, b);
  83.     cout << "= ";
  84.     PrintBigInt(c);
  85.     cout << endl;
  86.     
  87.     unsigned int n;
  88.     cin >> n;
  89.     //cout << n << "! = ";
  90. // c = FacBigInt(n);
  91. // PrintBigInt(c);
  92. // cout << c.size << endl;
  93.      cout << endl;

  94.     cout << " ";
  95.     PrintBigInt(a);
  96.     cout << "^" << n << " = ";
  97.     PowBigInt(c, a, n);
  98.     PrintBigInt(c);
  99.     cout << endl;
  100.     
  101.     cout << " ";
  102.     PrintBigInt(a);
  103.     cout << "^" << n << " = ";
  104.     PowBigInt_2(c, a, n);
  105.     PrintBigInt(c);
  106.     cout << endl;
  107.     
  108.     system("pause");
  109.     return 0;
  110. }
  111. /*
  112. 函数名称:PrintBigInt
  113. 函数功能:输出用整型数组表示的高精度整数
  114. 输入参数:const BigInt & a:用整型数组表示的高精度整数
  115. 输出参数:无
  116. */
  117. void PrintBigInt(const BigInt & a)
  118. {
  119.     cout << a.val[a.size-1];
  120.     for (int i=a.size-2; i>=0; i--)
  121.     {
  122.         unsigned w = WIDTHMAX / 10;
  123.         while (w > 0)
  124.         {
  125.             if (a.val[i] >= w)
  126.                 break;
  127.             cout << 0;
  128.             w /= 10;
  129.         }
  130.         cout << a.val[i];
  131.     }
  132.     cout << endl;
  133. }
  134. /*
  135. 函数名称:StrToBigInt
  136. 函数功能:把元素为数字的字符串转换为用整型数组表示的高精度整数
  137. 输入参数:string s:存储数字的字符串
  138. 输出参数:BigInt:返回用整型数组表示的高精度整数
  139. */
  140. BigInt StrToBigInt(string s)
  141. {
  142.     BigInt a;
  143.     a.size = 0;
  144.     int i = s.size();
  145.     unsigned long long sum = 0;
  146.     while ( i>=WIDTH)
  147.     {
  148.         for (int j=i-WIDTH; j<i; j++)
  149.             sum = sum * 10 + (s[j] - '0');
  150.         a.val[a.size++] = sum;
  151.         sum = 0;
  152.         i -= WIDTH;
  153.     }
  154.     if (i > 0)
  155.     {
  156.         for (int j=0; j<i; j++)
  157.             sum = sum * 10 + (s[j] - '0');
  158.         a.val[a.size++] = sum;
  159.     }
  160.     return a;
  161. }
  162. /*
  163. 函数名称:AddBigInt
  164. 函数功能:高精度整数加法
  165. 输入参数:const BigInt & a:用整型数组表示的高精度整数加数
  166.           const BigInt & b:用整型数组表示的高精度整数加数
  167. 输出参数:BigInt:返回用整型数组表示的高精度整数和
  168. */
  169. BigInt AddBigInt(const BigInt & a, const BigInt & b)
  170. {
  171.     //逆序计算a+b,则从低位开始计算
  172.     BigInt c;
  173.     unsigned long long carry = 0;
  174.     unsigned int i = 0;
  175.     c.size = 0;
  176.     while (i < a.size && i < b.size)
  177.     {
  178.         c.val[c.size++] = (a.val[i] + b.val[i] + carry) % WIDTHMAX;
  179.         carry = (a.val[i] + b.val[i] + carry) / WIDTHMAX;
  180.         i++;
  181.     }
  182.     while (i < a.size)
  183.     {
  184.         c.val[c.size++] = (a.val[i] + carry) % WIDTHMAX;
  185.         carry = (a.val[i] + carry) / WIDTHMAX;
  186.         i++;
  187.     }
  188.     while (i < b.size)
  189.     {
  190.         c.val[c.size++] = (b.val[i] + carry) % WIDTHMAX;
  191.         carry = (b.val[i] + carry) / WIDTHMAX;
  192.         i++;
  193.     }
  194.     if (carry > 0)
  195.         c.val[c.size++] = carry;
  196.     return c;
  197. }
  198. /*
  199. 函数名称:SubBigInt
  200. 函数功能:高精度整数减法
  201. 输入参数:BigInt a:用整型数组表示的高精度整数被减数
  202.           BigInt b:用整型数组表示的高精度整数减数
  203. 输出参数:BigInt:返回用整型数组表示的高精度整数差
  204. */
  205. BigInt SubBigInt(BigInt a, BigInt b)
  206. {
  207.     BigInt c;
  208.     c.size = 0;
  209.     if (ComPareBigInt(a, b) == 0)
  210.     {
  211.         c.size = 1;
  212.         c.val[0] = 0;
  213.         return c;
  214.     }
  215.     bool flag = false;
  216.     if (ComPareBigInt(a, b) < 0)//交换,并得到一个负号
  217.     {
  218.         flag = true;
  219.         BigInt temp = a;
  220.         a = b;
  221.         b = temp;
  222.     }
  223.     unsigned int i = 0;
  224.     while (i < b.size)
  225.     {
  226.         if (a.val[i] >= b.val[i])
  227.              c.val[c.size++] = a.val[i] - b.val[i];
  228.         else
  229.         {
  230.             a.val[i+1] -= 1;
  231.             c.val[c.size++] = a.val[i] + WIDTHMAX - b.val[i];
  232.         }
  233.         i++;
  234.     }
  235.     while (i < a.size)
  236.     {
  237.         if (a.val[i] < 0)
  238.         {
  239.             a.val[i+1] -= 1;
  240.             a.val[i] += WIDTHMAX;
  241.         }
  242.         c.val[c.size++] = a.val[i];
  243.         i++;
  244.     }
  245.     //消除多余的高位0
  246.     while (c.val[c.size-1] == 0)
  247.         c.size--;
  248.            
  249.     if (flag)//如果是负数,加上负号
  250.         c.val[c.size-1] = -c.val[c.size-1];
  251.     return c;
  252. }
  253. /*
  254. 函数名称:ComPareBigInt
  255. 函数功能:比较两个高精度整数的大小
  256. 输入参数:BigInt a:用整型数组表示的高精度整数被减数
  257.           BigInt b:用整型数组表示的高精度整数减数
  258. 输出参数:int:a > b返回1,a = b返回0,a < b返回-1
  259. */
  260. int ComPareBigInt(const BigInt & a, const BigInt & b)
  261. {
  262.     if (a.size > b.size)
  263.         return 1;
  264.     if (a.size < b.size)
  265.         return -1;
  266.         
  267.     for (int i=a.size-1; i>=0; i--)
  268.     {
  269.         if (a.val[i] > b.val[i])
  270.             return 1;
  271.         if (a.val[i] < b.val[i])
  272.             return -1;
  273.     }
  274.     return 0;
  275. }
  276. /*
  277. 函数名称:MulBigInt
  278. 函数功能:高精度整数乘法
  279. 输入参数:const BigInt & a:用整型数组表示的高精度整数被乘数
  280.           const BigInt & b:用整型数组表示的高精度整数乘数
  281. 输出参数:BigInt:返回用整型数组表示的高精度整数乘积
  282. */
  283. BigInt MulBigInt(const BigInt & a, const BigInt & b)
  284. {
  285.     if (a.size == 1 && a.val[0] == 0)
  286.         return a;
  287.     if (b.size == 1 && b.val[0] == 0)
  288.         return b;

  289.     BigInt c;
  290.     for (int i=0; i<MAX; i++) //全部赋初值为0
  291.         c.val[i] = 0;
  292.     for (int i=0, j=0; i<b.size; i++)
  293.     {
  294.         for (j=0; j<a.size; j++)
  295.         {
  296.             c.val[i+j] += a.val[j] * b.val[i];
  297.             c.val[i+j+1] += c.val[i+j] / WIDTHMAX;
  298.             c.val[i+j] %= WIDTHMAX;
  299.         }
  300.         c.size = i + j;
  301.         if (c.val[c.size] != 0)//最高位有进位
  302.             c.size++;
  303.     }
  304.     return c;
  305. }
  306. /*
  307. 老版本:
  308. BigInt MulBigInt2(const BigInt & a, const BigInt & b)
  309. {
  310.     if (a.size == 1 && a.val[0] == 0)
  311.         return a;
  312.     if (b.size == 1 && b.val[0] == 0)
  313.         return b;

  314.     BigInt c, tc;
  315.     unsigned long long carry = 0;
  316.     c.size = 0;
  317.     for (int i=0, j=0; i<b.size; i++)
  318.     {
  319.         for (j=0; j<i; j++)//先在临时和tc的低位补足0
  320.             tc.val[j] = 0;
  321.         carry = 0;
  322.         for (j=0; j<a.size; j++)
  323.         {
  324.             tc.val[i+j] = (a.val[j] * b.val[i] + carry) % WIDTHMAX;
  325.             carry = (a.val[j] * b.val[i] + carry) / WIDTHMAX;
  326.         }
  327.         tc.size = i + j;
  328.         if (carry > 0)
  329.             tc.val[tc.size++] = carry;
  330.         //累加到c中
  331.         c = AddBigInt(tc, c);
  332.     }
  333.     return c;
  334. }
  335. */

  336. /*
  337. 函数名称:FacBigInt
  338. 函数功能:高精度整数阶乘
  339. 输入参数:unsigned int n:正整数
  340. 输出参数:BigInt:返回用整型数组表示的高精度整数阶乘
  341. */
  342. BigInt FacBigInt(unsigned int n)
  343. {
  344.     BigInt s, c;
  345.     c.size = s.size = 1;
  346.     s.val[0] = 1;
  347.     for (unsigned long long i=2; i<=n; i++)
  348.     {
  349.         c.val[0] = i;
  350.         s = MulBigInt(s, c);
  351.     }
  352.     return s;
  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. 函数名称:PowBigInt_2
  382. 函数功能:非递归高效算法求高精度整数幂
  383. 输入参数:BigInt & c:存储高精度整数幂的整型数组
  384.           const BigInt & a:用整型数组表示的高精度整数底数
  385.           long long n: 指数
  386. */
  387. void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n)
  388. {
  389.     int stack[MAX] = {0};
  390.     int top = 0;
  391.     while (n > 0) //利用一个栈来存储n的状态:奇数还是偶数
  392.     {
  393.         stack[top++] = n % 2;
  394.         n /= 2;
  395.     }
  396.     c.size = c.val[0] = 1;
  397.     for (int i=top-1; i>=0; i--)
  398.     {
  399.         c = MulBigInt(c, c); //a^n = a^(n/2)*a^(n/2)*f(a)
  400.         if (stack[i] == 1) //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)
  401.             c = MulBigInt(a, c);
  402.     }
  403. }

  404. /*
  405. 函数名称:DivBigInt
  406. 函数功能:二分法实现高精度整数除法
  407. 输入参数:const BigInt & a:用整型数组表示的高精度整数被除数
  408.           const BigInt & b:用整型数组表示的高精度整数除数
  409. 输出参数:BigInt:返回用整型数组表示的高精度整数商
  410. */
  411. BigInt DivBigInt(const BigInt & a, const BigInt & b)
  412. {
  413.     BigInt high, low, mid, one, c;
  414.     if ((a.size == 1 && a.val[0] == 0) || (b.size == 1 && b.val[0] == 0))
  415.     {
  416.         c.size = 1;
  417.         c.val[0] = 0;
  418.         return c;
  419.     }
  420.     
  421.     one.size = 1; //值为1的高精度整数
  422.     one.val[0] = 1;
  423.     high = a; //上界
  424.     low.size = 1; //下界
  425.     low.val[0] = 0;
  426.     while (ComPareBigInt(low, high) < 0)
  427.     {
  428.         mid = HalfBigInt(AddBigInt(high, low)); //中间数
  429.         c = MulBigInt(mid, b);
  430.         if (ComPareBigInt(c, a) == 0)
  431.             return mid;
  432.         else if (ComPareBigInt(c, a) < 0)
  433.             low = AddBigInt(mid, one);
  434.         else
  435.             high = SubBigInt(mid, one);
  436.     }
  437.     c = MulBigInt(low, b);
  438.     if (ComPareBigInt(c, a) <= 0)
  439.         return low;
  440.     else
  441.         return SubBigInt(low, one);
  442. }

  443. /*
  444. 函数名称:HalfBigInt
  445. 函数功能:高精度整数求半
  446. 输入参数:BigInt a:用整型数组表示的高精度整数
  447. 输出参数:BigInt:返回用整型数组表示的高精度整数的一半
  448. */
  449. BigInt HalfBigInt(BigInt a)
  450. {
  451.     BigInt c;
  452.     c.size = a.size;
  453.     for (int i=a.size-1; i>0; i--)
  454.     {
  455.         c.val[i] = a.val[i] / 2;
  456.         if (a.val[i] % 2 == 1)
  457.             a.val[i-1] += WIDTHMAX;
  458.     }
  459.     c.val[0] = a.val[0] / 2;
  460.     if (c.size > 0 && c.val[c.size-1] == 0)
  461.         c.size--;
  462.         
  463.     return c;
  464. }
阅读(3237) | 评论(1) | 转发(1) |
1

上一篇:高精度加法

下一篇:约瑟夫问题

给主人留下些什么吧!~~

rrammstein2013-03-26 11:22:47

很好!收藏了再说!