大整数乘法

问题描述

                                                            by 计算机算法设计与分析 王晓东 P17

通常,在分析一个算法的计算复杂性时,都将加法和乘法运算当作是基本运算来处理,即将执行一次加法或乘法运算所需的计算时间当作一个仅取决于计算机硬件处理速度的常数。

这个假定仅在计算机硬件能对参加运算的整数直接表示和处理时才是合理的。然而,在某些情况下,我们要处理很大的整数,它无法在计算机硬件能直接表示的范围内进行处理。若用浮点数来表示它,则只能近似地表示它的大小,计算结果中的有效数字也受到限制。若要精确地表示大整数并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算XY都是n位的二进制整数,现在要计算它们的乘积XY。我们可以用小学所学的方法来设计一个计算乘积XY的算法,但是这样做计算步骤太多,显得效率较低。如果将每21位数的乘法或加法看作一步运算,那么这种方法要作O(n2)步运算才能求出乘积XY。下面我们用分治法来设计一个更有效的大整数乘积算法。

 大整数乘法

                            图6-3 大整数XY的分段 

我们将n位的二进制整数XY各分为2段,每段的长为n/2(为简单起见,假设n2的幂),如图6-3所示。

由此,X=A2n/2+B ,Y=C2n/2+D。这样,XY的乘积为:

XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD             (1)

如果按式(1)计算XY,则我们必须进行4n/2位整数的乘法(ACADBCBD)
以及3次不超过n位的整数加法(分别对应于式(1)中的加号),此外还要做2次移位(分别对应于式(1)中乘2n和乘2n/2)。所有这些加法和移位共用O(n)步运算。

XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD                     (2)

虽然,式(2)看起来比式(1)复杂些,但它仅需做3n/2位整数的乘法(ACBD(A-B)(D-C))6次加、减法和2次移位。

X=314l,Y=5327,用上述算法计算XY的计算过程可列表如下,其中带'号的数值是在计算完成ACBD,和(A-B)(D-C)之后才填入的。


X=3141        A=31       B=41        A-B=-10

Y=5327        C=53       D=27        D-C=-26

           AC=(1643)'

           BD=(1107)'

          (A-B)(D-C)=(260)'

XY=(1643)'104+[(1643)'+(260)'+(1107)']102+(1107)'

  =(16732107)'


A=31        A1=3       B1=1        A1-B1=2

C=53        C1=5       D1=3        D1-C1=-2

           A1C1=15     B1D1=3     (A1-B1)(D1-C1)=-4

AC=1500+(15+3-4)10+3=1643


B=41        A2=4       B2=1        A2-B2=3

D=27        C2=2       D2=7        D2-C2=5

           A2C2=8     B2D2=7     (A2-B2)(D2-C2)=15

BD=800+(8+7+15)10+7=1107


|A-B|=10        A3=1       B3=0        A3-B3=1

|D-C|=26        C3=2       D3=6        D3-C3=4

           A3C3=2     B3D3=0     (A3-B3)(D3-C3)=4

(A-B)(D-C)=200+(2+0+4)10+0=260


 

#define CLOCKS_PER_SEC 1000

#define LENGTH 10

#include <iostream>

//#include <stdafx.h>

#include <sys/timeb.h>

#include <time.h>

#include <stdlib.h>

#include <iomanip>

#include <vector>

#include <algorithm>

#include <cstring>

#include <cmath>

#include <stdio.h>

#include <cstdlib>

#include<fstream>

#define NUMBER 10000

using namespace std;

void myself()

{

long a,b;

while(cin>>a>>b)

{

long A;

long B;

long C;

long D;

B=a%NUMBER;

D=b%NUMBER;

A=(a-B)/NUMBER;

C=(b-D)/NUMBER;

long re1,re2,re3;

re1=A*C;

re2=B*C+A*D;

re3=B*D;

re2=re2+(re3-re3%NUMBER)/NUMBER;

re3=re3%NUMBER;

re1=re1+(re2-re2%NUMBER)/NUMBER;

re2=re2%NUMBER;

cout<<a<<"*"<<b<<"="<<re1<<re2<<re3<<endl;

}

}

int main(void)

{

clock_t t1,t2;

t1=clock();

myself();

t2=clock();

cout<<"消耗时间-"<<"\t"<<((double)(t2-t1)/(double)CLOCKS_PER_SEC)*10000.0<<"ms"<<endl; 

return 0; 

}

这个程序可以完成八位十进制数与八位十进制数的乘法计算,再多估计就无法满足要求;;;
主要的限制在于long类型的整数对乘法结果大小的限制。。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值