zoukankan      html  css  js  c++  java
  • 高效大数模板

      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
  • 相关阅读:
    NodeJs学习历程
    MongoDb学习历程
    递归函数为什么要防止栈溢出
    *args 是可变参数,args 接收的是一个 tuple; **kw 是关键字参数,kw 接收的是一个 dict。
    list和tuple的区别
    python源码阅读
    常用的线程池有哪些?
    备份
    假设你正在爬楼梯,需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶,你有多少种不同的方法可以爬到楼顶呢?
    最后一个单词的长度
  • 原文地址:https://www.cnblogs.com/Skyxj/p/3185064.html
Copyright © 2011-2022 走看看