分治法 --- 大整数的乘法

原创 2010年05月26日 16:48:00

  大整数的乘法

 

       在计算机中,长整形(long int)变量的范围是-2147483648至2147483647,因此若用长整形变量做乘法运算,乘积最多不能超过10位数。即便用双精度(double)变量,也仅能保证16位有效数字的精度。在某些需要更高精度的乘法运算场合,需要用别的办法来实现运算。

      比较容易想到的是做多位数乘法时列竖式进行计算的方法,只要写出模拟这一过程的程序,就能实现任意大整数的乘法运算。经过查阅资料,找到一种更易于编程的方法,即“列表法”。

 

下面先介绍“列表法”:

例如当计算8765*234时,把乘数和被乘数照如下列出,见表1:

 

8

7

6

5

*

16

14

12

10

2

24

21

18

15

3

32

28

24

20

4

 

                           表一

 

 

 

16

14

12

10

 

 

 

24

21

18

15

 

 

 

32

28

24

20

16

38

65

56

39

20

 

   

 

16

38

65

56

39

20

2

16+4=20

38+7=45

65+6=71

56+4=60

39+2=41

 

2

02

54

17

06

14

02

2

0

5

1

0

1

0

 

  根据以上思路 就可以编写C程序了,再经分析可得:

1,一个m位的整数与一个n位的整数相乘,乘积为m+n-1位或m+n位。

2,程序中,用三个字符数组分别存储乘数,被乘数与乘积。由第1点分析知,存放乘积的字符数组饿长度应不小于存放乘数与被乘数的两个数组的长度之和。

3,可以把第二步“计算填表”与第三四步“累加进位”放在一起完成,可以节省存储表格2所需的空间。

4,程序关键部分是两层循环,内层循环累计一数组的和,外层循环处理保留的数字和进位。

效率分析:用以上算法计算m位整数乘以n位整数,需要先进行m*n次乘法,再进行约m+n次加法运算和m+n次取模运算(实为整数除法)。把这个程序稍加修改,让它自己生产乘数和被乘数,然后计算机随机的7200为整数互乘。

   经过改进,此算法效率可以提高约9倍。

    注意到以下事实:8216547*96785 将两数从个位起,每3位分为节,列出乘法表,将斜线间的数字相加:

    8  216  547

         96   785

8

216

547

*

768

20736

52512

96

6250

169560

429395

785

 

768

20736

52512

 

 

6250

169560

429395

768

27016

222072

429395

 

 

 

将表中最后一行进行如下处理:从个位数开始,每一个方格里只保留三个数字,超出1000的部分进位到前一个方格里:

  

 

768

27016

222072

429395

 

768+27=795

27016+222=27238

222072+429=222501

395429

 

795

238

501

395

所以8216547*96785 = 795238501395

 

 也就是说我们在计算生成这个二维表时,不必一位一位的乘,而可以三位三位的乘;在累加时也是满1000进位。这样,我们计算m位整数乘以n位整数,只需要进行m*n/9次乘法运算,再进行约(m+n)/3次加法运算和(m+n)/3次去摸运算。总体看来,效率是前一种算法的9倍。

  有人可能会想:既然能用三位三位的乘,为什么不能4位4位的乘,甚至5位。听我解来:本算法在累加表中斜线间的数字时,如果用无符号长整数(范围0至~4294967295)作为累加变量,在最不利的情况下(两个乘数的所有数字均为9),能够累加约4294967295/(999*999)=4300次,也就是能够准确计算任意两个约不超过12900(每次累加的结果“值”三位,故4300*3=12900)位的整数相乘。如果4位4位地乘,在最不利的情况下,能过累加月4294967295/(9999*9999)=43次,仅能够确保任意两个不超过172位的整数相乘,没什么实用价值,更不要说5位了。

 

  

 

 

  

  

 

 

                           表二

  从最低位的20开始,保留个位数字“0”,把个位以外的数“2”进到前一位;把次低位的39加上低位进上来的2得41,保留个位数字“1”,把“4”进到前一位;以此类推,直至最高位的16,16加上地位进上来的4得20,保留“0”,把2进到最高位,得乘积为

< < 深度探索C++模型> > 提问(第三章)(上)

 第三章:Data语意学1.  一个class的object的大小一般受到那三个因素的影响?(P84-P85)2.  一个空的class的大小是多少?为什么?(P84)3.  一个empty virt...
  • codingcoding
  • codingcoding
  • 2002-10-28 09:34:00
  • 456

两个任意长度的长整数相乘(华为oj,C++)

#include #include typedef struct NODE { struct NODE * pUp; int shuzhi; struct NODE * pNext; }*...
  • IvaanLove
  • IvaanLove
  • 2016-02-04 15:11:36
  • 5646

Java实现大整数相乘

用数组的方式实现,直接贴上代码: /* * 大整数乘法 */ public class Demo9 { static int N=100; static int a[]=new...
  • yeruby
  • yeruby
  • 2013-09-25 17:51:13
  • 12795

分治法的经典问题——大整数相乘

请设计一个有效的算法,可以进行两个n位大整数的乘法运算。 参考解答设X和Y都是n位的二进制整数,现在要计算它们的乘积XY。我们可以用小学所学的方法来设计一个计算乘积XY的算法,但是这样做计算步骤太多,...
  • wangyangkobe
  • wangyangkobe
  • 2011-05-26 12:32:00
  • 34347

两个任意长度的长整数相乘(C语言、双向链表方法)

两个任意长度的长整数相乘, 输出结果
  • IvaanLove
  • IvaanLove
  • 2016-02-04 00:48:34
  • 2219

英雄会-----任意长度的两个正整数相乘

任意长度的两个正整数相乘 题目:        两个大数相乘:char* multiply(char*,char*)。给了两个字符串,每个都是代表了一个很长的10进制表示的数, 比如 String s...
  • crazy1235
  • crazy1235
  • 2014-02-08 10:13:51
  • 2922

关于两个长整数相乘的实现

题目:实现两个长整数相乘的算法。 此代码可实现任意长度的两个数相乘,实现方法采用单向链表。 以下是我的代码.备注:此代码有参考网上的代码。#include"stdafx.h"#include    u...
  • md521
  • md521
  • 2010-10-18 22:04:00
  • 1715

实现长整数的相乘

Code:#include #include #define N 20 //长整数的位数 #define M 100 //储存乘法结果 int main() { int i,...
  • guidianshuxue
  • guidianshuxue
  • 2011-03-29 20:35:00
  • 353

快速傅里叶变换用于长整数相乘

作图代码:data = [] with open('fft-ifft.txt','r') as f: for line in f: splitlist = line.repl...
  • u012176591
  • u012176591
  • 2015-07-05 23:36:40
  • 1426

两个长整数相乘

#include #include using namespace std;  #define MAX_USHORT 65536#define MAX_UCHAR  256 void Foo(unsi...
  • SammyLan
  • SammyLan
  • 2006-04-10 00:26:00
  • 1462
收藏助手
不良信息举报
您举报文章:分治法 --- 大整数的乘法
举报原因:
原因补充:

(最多只允许输入30个字)