大数问题

大数是指计算的数值非常大或者对运算的精度要求非常高,用已知的数据类型无法精确表示的数值。

大数问题主要有以下四种:

==================================

1. 大数相加

2. 大数相乘

3. 大数阶乘

4. 大数幂乘

==================================

下面我们一起解决这四种问题。

 

Problem 1 大数相加

一般的int,long等类型无法精确表达数值。

我们就考虑以字符串的形式读入这两个数,利用vector来表示这两个数值,

代码:

 1 string s1, s2;
 2 cin>>s1>>s2;
 3 int i;
 4 vector<int> v1(s1.size()), v2(s2.size());
 5 for(i = 0; i < s1.size(); i++)
 6 {
 7     v1[i] = s1[i] - '0';
 8 }
 9 for(i = 0; i < s2.size(); i++)
10 {
11     v2[i] = s2[i] - '0';
12 }

 

利用vector的空间可以无限扩展,因此我们利用vector来模拟计算这两个数的相加。

根据加法规则我们可以知道,个位与个位相加,十位与十位相加...

代码:

 1 vector<int> f(vector<int> v1, vector<int> v2)
 2 {
    #将两个数字的位置倒过来,个位数字放在最前面,例如:123,倒过来即为321
3 reverse(v1.begin(),v1.end()); 4 reverse(v2.begin(),v2.end()); 5 int maxsize = v1.size();
    #比较两个数字的位数,找到最长的
6 if(v2.size() > maxsize) 7 { 8 maxsize = v2.size(); 9 } 10 vector<int> v3(maxsize);
    #记录每一位计算的进位
11 int carry = 0; 12 int i; 13 for(int i = 0; i < maxsize; i++) 14 { 15 int t = carry; 16 if(i < v1.size()) 17 t = t + v1[i]; 18 if(i < v2.size()) 19 t = t + v2[i];
      #当相同位置上的数字相加超过10时,应该向高位进位
20 carry = t / 10; 21 v3[i] = t % 10; 22 }
    #若最高位相加之后,需要进位,那么我们需要扩展vector
23 if(carry > 0) 24 v3.push_back(carry);
    #最后将vector倒置,可以得到最终的相加结果
25 reverse(v3.begin(),v3.end()); 26 return v3; 27 }

 

Problem 2 大数相乘

例如:

位置: 4  3  2  1  0

数值1:         4  3  2

数值2:         *     4     5

------------------------------------

结果:        20    15  10

     16  12    8

-----------------------------------

    16  32  23  10

-----------------------------------

  1     9    4   4    0

从上面的例子中我们可以看出位置i和位置j的结果放在i+j的位置,最后再依次进行进位操作。

代码:

这里要注意初始结果申请的空间,最后在输出的时候需要进行处理。

 1 vector<int> m(vector<int> v1, vector<int> v2)
 2 {
 3     reverse(v1.begin(),v1.end());
 4     reverse(v2.begin(),v2.end());
 5     int maxsize = v1.size();
 6     if(v2.size() > maxsize)
 7         maxsize = v2.size();
 8     maxsize *= 2;
 9     vector<int> v3(maxsize, 0);
10     int carry = 0;
11     for(int i = 0; i < v1.size(); i++)
12         for(int j = 0; j < v2.size(); j++)
13         {
14             v3[i+j] += v1[i]*v2[j];
15         }
16     for(int i = 0; i < v3.size(); i++)
17     {
18         if(v3[i] >= 10)
19         {
20             v3[i+1] += v3[i]/10;
21             v3[i] = v3[i] % 10;
22         }
23     }
24     reverse(v3.begin(),v3.end());
25     
26     return v3;    
27 }

 输出处理:因为开始申请的空间可能有部分没有用到,但是在倒置的时候最前面可能出现多个0,利用flag记录非0的起点。

代码:

int flag = 0;
while(v4[flag] == 0)
    flag++;
for(i = flag; i < v4.size(); i++)
    cout<<v4[i];
cout<<endl;

 

Problem 3大数阶乘

一般阶乘很快就会超过int的表达范围,因此同样采用上面大数相乘的思想来计算大数阶乘,这里需要注意的是开始输入的n不是一个大数,但是随着计算,结果会越来越大。

 利用循环来计算大数阶乘。

代码:

 1 vector<int> m(vector<int> v1, vector<int> v2)
 2 {
 3     reverse(v1.begin(),v1.end());
 4     reverse(v2.begin(),v2.end());
 5     int maxsize = v1.size();
 6     if(v2.size() > maxsize)
 7         maxsize = v2.size();
 8     maxsize *= 2;
 9     vector<int> v3(maxsize, 0);
10     int carry = 0;
11     for(int i = 0; i < v1.size(); i++)
12         for(int j = 0; j < v2.size(); j++)
13         {
14             v3[i+j] += v1[i]*v2[j];
15         }
16     for(int i = 0; i < v3.size(); i++)
17     {
18         if(v3[i] >= 10)
19         {
20             v3[i+1] += v3[i]/10;
21             v3[i] = v3[i] % 10;
22         }
23     }
24     reverse(v3.begin(),v3.end());
25     
26     return v3;    
27 }
28 
29 vector<int> intTovector(int x)
30 {
31     vector<int> v;
32     while (x)
33     {
34         v.push_back(x%10);
35         x /= 10;
36     }
37     reverse(v.begin(),v.end());
38     return v;
39 }
40 
41 vector<int> pre(vector<int> v)
42 {
43     vector<int> v1;
44     int flag = 0;
45     while(v[flag] == 0)
46         flag++;
47     for(int i = flag; i < v.size(); i++)
48         v1.push_back(v[i]);
49     return v1;
50 }
51 
52 void p(vector<int> v)
53 {
54     for(int j = 0; j < v.size(); j++)
55             cout<<v[j];
56         cout << endl;
57 }
58 
59 vector<int> jiecheng(int n)
60 {
61     vector<int> v1(1,1);
62     if(n == 1)
63         return v1;
64     vector<int> v2(1,2);
65     if(n == 2)
66         return v2;
67     vector<int> v3 = v2;
68     for(int i = 3; i <= n; i++)
69     {
70         vector<int> t1 = intTovector(i);
71         p(t1);
72         vector<int> t2 = v3;
73         p(t2);
74         v3 = pre(m(t1,t2));
75         p(v3);
76         cout << "===============" <<endl;
77     }
78     return v3;
79 }

 

 

Problem 4大数幂乘

一般阶乘很快就会超过int的表达范围,因此同样采用上面大数相乘的思想来循环计算大数阶乘。

代码:

 1 vector<int> micheng(int n, int s)
 2 {
 3     vector<int> v = intTovector(n);
 4     for(int i = 1; i < s; i++)
 5     {
 6         v = pre(m(v,intTovector(n)));
 7         
 8     }
 9     return v;
10 }

 

 

 

         

 

 

 

posted @ 2014-05-16 11:22  panpannju  阅读(913)  评论(0编辑  收藏  举报