高精度乘法

乘法的运算受限于数据类型的表示范围,比如int类型的乘法,32位的无符号整形

                 unsigned int 最大可表示0xffffffff

有时问题会要求我们进行较大的数值的计算,我们除了使用表示范围较大的数据类型(事实上,这仍不可靠)外,还可以选择高精度的乘法模拟。

例如,有这么一个问题:输入一个不超过1000的正整数n,输出n!的精确结果。

显然int类型来表示这个结果会产生溢出。

下面简单讲讲高精度乘法的一般过程:高精度乘法要求我们开一个数组(假设用f[maxn]表示),用其中的每一位代表运算结果的每一位。因此,我们要对问题要求的计算结果进行分析,估算大致位数,来决定maxn的大小,就这个例子看来,最大的输出结果1000!约有2600位,故开辟一个3000维的数组足够保存结果。

进行乘法模拟,不失一般性,取一次乘法过程来模拟,被乘数已经存放在f数组中,乘数是x,算法伪代码如下

1 For j=1 to maxn 
2     int s ← f[j]*被乘数 + 进位;  
3     f[j] ← s % 10;                  //求解每一位的值            
4     进位 ← s / 10;                   //求解余数

模拟的算法相当简单:就是对被乘数的每一位,都乘以乘数,并加上进位(初始化为0),并更新f数组的值。

每一遍计算完成后,f数组中保存的就是结果的每一位的值,当然,这里还可以压缩下外循环,因为每次f中保存的值的有效位数是确定的,就可以根据有效位数来决定外循环次数,不一定要每次都执行maxn遍。

模拟方法讲完了,接下来就来解决一下上面的问题,代码用C++实现:

 1 #include<iostream>
 2 #include<cstring>
 3 #define   maxn   3000                         //数组开足够大,这里3000即可 
 4 using namespace std;
 5 int    f[maxn];
 6 int main(){
 7     int n;
 8     cin >> n;                                       //输出n! 
 9     memset(f, 0, sizeof(f));              //初始化为全0
10     f[1] = 1;                                 //f数组保存被乘数,即每一次的运算结果
11     for(int i =2; i <= n; ++i){            //计算n-1次 
12         int c = 0;                          //进位初始化
13         for(int j = 1; j <= maxn; ++j){ //遍历每一位
14             int s = f[j] * i + c;
15             f[j] = s % 10;
16             c = s / 10;
17         } 
18     }
19     int beg;
20     for(beg = maxn; beg >= 1; --beg)    //忽略前导的0 
21         if(f[beg]) break;
22     for(int i = beg; i >= 1; --i)
23         cout<<f[i];
24     return 0; 
25 }     

后记:博客园的第一篇随笔,随便水一下2333

怕什么真理无穷,进一寸有一寸的欢喜
原文地址:https://www.cnblogs.com/HolyShine/p/5510145.html