您的位置:首页 > 其它

高精度乘法

2016-05-19 21:06 225 查看

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

                 unsigned int 最大可表示0xffffffff

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

 

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

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

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

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

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

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

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

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

#include<iostream>
#include<cstring>
#define   maxn   3000                         //数组开足够大,这里3000即可
using namespace std;
int    f[maxn];
int main(){
int n;
cin >> n;                                       //输出n!
memset(f, 0, sizeof(f));              //初始化为全0
f[1] = 1;                                 //f数组保存被乘数,即每一次的运算结果
for(int i =2; i <= n; ++i){            //计算n-1次
int c = 0;                          //进位初始化
for(int j = 1; j <= maxn; ++j){ //遍历每一位
int s = f[j] * i + c;
f[j] = s % 10;
c = s / 10;
}
}
int beg;
for(beg = maxn; beg >= 1; --beg)    //忽略前导的0
if(f[beg]) break;
for(int i = beg; i >= 1; --i)
cout<<f[i];
return 0;
}

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

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: