您的位置:首页 > 理论基础

计算机求解可溢出的两个整型数相乘,算数运算溢出解决方法

2013-09-05 09:43 162 查看
计算机求解可溢出的两个整型数相乘

滕金国

(陕西师范大学 计算机科学学院,陕西西安 710062)

摘 要:, 跟据两个数相乘的规律,利用数组来存储两个整形数相乘的结果,从而解决了相乘溢出的问题,得到两个整形数相乘的精确结果

关键词: 相乘;溢出;数组存储

ComputerSolving integer overflow of the two multiplied

Tengjinguo

(1.Dept. of Computer science , Shannxi normal University, Xi’an ShanXi 710062, China)

Abstract: With the two numbers multiplied,according to the law, using an array to store the two integer multiplied thenumber of results, so as to solve a multiplication overflow problem, get twointeger multiplied the number of accurate results

Keywords: Multiply; Integer;overflow; array of storage;

1 引言
计算机内所采用的任何记数法所使用的位模式的长度是限定的,所能表示的数值范围因此是确定的。当进行运算时,可能会遇到因结果不在所表示的数的范围,从而发生了溢出。溢出问题是计算机编程中常见的问题,数值溢出大多是不会引起编译错误的,并且在很多情况下,编译程序没有给出溢出信息,但数值溢出会使运行结果发生偏差. 两个整形数相乘也是如此,当乘积过大时也会溢出。用数组来存储两个整形数相乘的结果,把用十进制表示的乘积的每一位(或n位)都对应的存放到数组中的每一个单元中,再按照一定的顺序输出时,便可得到正确的结果。


2 算法设计

2.1 两个数相乘的过程

利用数组进行两数相乘的算法的模拟过程用下面的例子说明:

设乘数a=999,乘数b=999,积存放在c中

(9)(8)(7)(6)(5)(4)(3)(2)(1)

C 0 0 0 0 0 0 0 0 0

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

由于两个乘数是三位数,故此例分三步:

(1) 首先用乘数b的(1)位与乘数a相乘:

考虑到此时乘积也有可能溢出(此题不会),故用b的(1)位与a的每一位分别相乘,第一次用b1乘以a1,并将结果放到c中的低两位。 第二次用b(1)乘以a(2)并将结果加到c的(2)、(3)位上。同理,第三次用b(1)乘以a(3)并把结果加到c的(3)(4)位上……

如下所示:

① C 0 0 0 0 0 0 0 0 0

+ 9 *9

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

② C 0 0 0 0 0 0 0 8 1

+ 9 *9

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

③ C 0 0 0 0 0 0 8 9 1

+ 9 *9

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

④ C 0 0 0 0 0 8 9 9 1

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

(2)用乘数b的(2)位与乘数a相乘:

方法原理同(1),与(1)不同的是:当b(2)与a的每一位相乘时,把结果从c的(2)、(3)位开始加,另外,两个两位数相加可能会有进位f。 设f的初始值为0,过程如下:

① C 0 0 0 0 0 8 9 9 1

+ 9 *9 +f*10

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

有进位设f=1

② C 0 0 0 0 0 8 8 0 1

+ 9 *9 +f*10

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

有进位设f=1

③ C 0 0 0 0 0 7 9 0 1

+ 9 *9 +f*10

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

④ C 0 0 0 0 9 8 9 0 1

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

没有进位设f=0

(3)用乘数b的(3)位与乘数a相乘:

同(2),此时把b3与a的每一位的的乘积从c的(3)(4)位开始加。 由(2)得,f=0:

① C 0 0 0 0 9 8 9 0 1

+ 9 *9 +f*10

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

有进位f=1

② C 0 0 0 0 9 7 0 0 1

+ 9 *9 +f*10

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

有进位f=1

③ C 0 0 0 0 8 8 0 0 1

+ 9 *9 +f*10

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

有进位f=1

④ C 0 0 0 9 9 8 0 0 1

A 0 0 0 0 0 0 9 9 9

B 0 0 0 0 0 0 9 9 9

998001就是a与b相乘的结果

2.1 两个数相乘的算法

此算法需要3个整形的数组,两个用来存放两个乘数,另一个用来存放乘积结果。从上面的例子可以看出,每次要从两个乘数中分别取一位进行乘法运算,并将结果与积中的两位数相加。完成这个过程需要用两个嵌套的循环,外层循环用来控制乘数的位数移动,内层循环来控制被乘数的位数移动。当内循环循环一次时表明乘数的一位已经和整个被乘数完成乘法运算。

用数组来实现这个过程,一是需要将一个整形数按位存放到数组中指定的位置;二是需要将数组中指定的几位转换为一个整形数。

该算法的的c++实现和描述方法如下:

#define N 100 /*数组的大小*/

#include<iostream>

using namespace std;

int s
,a
,b
; /*数组a和b存放两个乘数,数组s用来存放结果*/

int m,n; /*m、n分别为乘数a和b十进制位数*/

voidPutIntoArray(int arr[],int a,int i,int j) /*把一个整数a的各个位放进数组的i到j位*/

{

int t;

t=a;

while(i<=j)

{

t=a%10;

a=a/10;

arr[i]=t;

i++;

}

}

intArrayToInt(int arr[],int i,int j)//将数组中第i到第j位的数转化为整数,从低到高算

{

int s=0;

for(;i<=j;j--)

s=arr[j]+s*10;

return s;

}

voidmultiple(int arr[],int a[],int b[])//进行乘法运算的主要算法,a数组和b数组中放的是要运算的数,结果放到arr数组中

{

int i,s=0,f=0,s1=0;

for(int j=0;j<m;j++)

for(i=0;i<n;i++)

{

s1=ArrayToInt(arr,i+j,i+j+1);

s=s1+a[j]*b[i]+f*10;

if((s-100)>=0)

{

s=s-100;

f=1;

}

else

f=0;

PutIntoArray(arr,s,i+j,i+j+1);

}

}

int _tmain(intargc, _TCHAR* argv[])

{

for(int i=0;i<100;i++)//初始化操作

{

s[i]=0;

a[i]=0;

b[i]=0;

}

cin>>m; //输入乘数a的位数

for( i=m-1;i>=0;i--)

cin>>a[i];

cin>>n; //输入乘数a的位数

for( i=n-1;i>=0;i--)

cin>>b[i];

multiple(s,a,b); //相乘的函数,结果放到s中

for(i=99;i>=0;i--) //输出乘积s的各位

{

if(f&&s[i]==0){}

else

{

f=0;

cout<<s[i]<<' ';

}

}

cout<<endl;

cout<<"Press Enter to Esc,Thankyou!";

getchar();

getchar();

return 0;

}

3 算法分析

定理1.算法1是可终止的。

证明:.

此算法有两个嵌套的for循环,循环次数分别为m,n,

因此该算法是可终止的是

定理2.算法1是有效的。

证明:

该算法主要思想是将两个数相乘的方法改为循环的按位相乘,其基本原理乘法法则。而且该算法已通过编程实现了。因此该算法是可终止的。

定理3.算法1的时间复杂度是O(m*n)。

证明:

有两个嵌套的for循环可知,该算法的时间复杂度为O(m*n)

定理4.算法1的空间复杂度是S(2(m+n))。

证明:

当存储相乘的两个的数的大小分别为m、n时候,乘积s的位数小于等于m+n-1的位数(根据乘法规律),并且可以完成正常的运算,得到正确的结果。所以总的空间复杂度为S(2*(m+n))。

4总 结

该算法在时间和空间复杂度不高的条件下解决了两个整形数的相乘结果溢出的问题,同时该算法也可实现两个在溢出范围之外的两个整数相乘的问题。通过此方法我们可以来利用计算机进行一些较大的整数的运算。利用此算法的两个整形数的相乘运算扩展为浮点数的乘法运算。我们可以利用它来求得一些数学问题的结果,如求的更高阶的阶层运算(n!)的正确结果。在一些的工业控制或大型计算中也可利用此算法来求得精确的结果。总之,该算法是一个行之有效而且用重要作用的算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: