您的位置:首页 > 编程语言 > Delphi

基于delphi的超长整数四则运算的实现

2012-09-25 13:58 549 查看
基于delphi的超长整数四则运算的实现

龚成清

(广东女子职业技术学院 计算机系,广东 广州511450)

摘 要:介绍了利用数组对超长整数的存储,把超长整数的计算转化为数组元素的运算,实现了超长整数的加、减、乘、除的四则运算。

关键词:超长整数;数组;运算

一、引言

在科学研究和工程计算里,经常会遇到一些很大很大的整数的计算问题,这些整数没有办法利用普通的微机直接用现有程序设计语言中的整数类型进行存储和计算,这样就给研究工作带来了障碍。本文在delphi的开发环境下顺利地解决了超长整数四则运算的计算。

二、超长整数的存储

在程序设计语言中,整数分成了三种类型,它们分别是短整型、整型、长整型。它们的性质和表示范围如下表所示:

类型
取值范围
所占位数
Shortint
-128..127
8-bit
Smallint
-32768..32767
16-bit
Longint
-2147483648..2147483647
32-bit
由上表可以看出长整型的绝对值最大是2147483648这个10位的数字,超过这个范围的数将不能用现有的数据类型直接存储。因此,用一维数组的元素来存储超长整数的数字将是一种很好的解决方法,在delphi中,一维数组的下标最大可以去到2147483647,也就是说,用一维数组的每一个元素存储超长整数的每一个数字,可以存储一个2147483647位的整数,这样就大大地扩展了计算机内整数的表示范围。如:要存储整数9876543210,用数组来存储超长整数有两种方式:

(一)数组下标的低位与超长整数的低位对应

A[1]
A[2]
A[3]
A[4]
A[5]
A[6]
A[7]
A[8]
A[9]
A[10]
0
1
2
3
4
5
6
7
8
9
(二)数组下标的低位与超长整数的高位对应

A[1]
A[2]
A[3]
A[4]
A[5]
A[6]
A[7]
A[8]
A[9]
A[10]
9
8
7
6
5
4
3
2
1
0
两种方法存储的实质是一样的,程序员可以根据自己的习惯选择其中的一种方式进行存储。本文采用第一种方式进行存储,存储过程如下:
const e = 10000; //数组的最大下标
type bits = -9..9;
lste = array[1..e] of bits;
var
num1,num2,pd:lste; //用num1和num2两个数组分别存储两个超长整数,pd存储结果

w1,w2:integer;//w1是第一个超长整数的位数,w2是第二个超长整数的位数

procedure readnum();//超长整数的存储过程,数字从窗口的edit框中输入

var

i:integer;

str:string;

begin

for i:=1 to e do//数组初始化

begin

pd[i]:= 0; num1[i]:=0 ; num2[i]:=0 ;

end;

str:=form1.num1_edit.Text;

w1:=length(str); //求出第一个数的位数

for i:=1 to w1 do //把第一个数的数字存储在num1的数组中

num1[w1-i+1]:=strtoint(str[i]);

str:= form1.num2_edit.Text;

w2:=length(str); //求出第二个数的位数

for i:=1 to w2 do//把第一个数的数字存储在num1的数组中

num2[w2-i+1]:=strtoint(str[i]);

end;

三、超长整数四则运算的实现

超长整数四则运算是指两个超长整数之间的加、减、乘、除的计算。用数组对超长整数进行存储后,就可以把超长整数的运算转化为数组元素之间的运算。
(一)超长整数相加
超长整数相加转化为对应的数组元素的相加,当两个数组元素与前一位的进位相加的和大于10的时候则向前进位,同时把和减去10后即得对应的两个数字的和。具体算法如下所示:
procedure TForm1.add_btnClick(Sender: TObject);
var

i, cr,count: integer;
result:string;
begin
readnum();
cr := 0; //cr
是进位
if w1<w2 then count:=w2 else count:=w1;
for i:=1 to count+1 do

begin
pd[i]:=num1[i]+num2[i]+cr; //两个数对应的各位相加
cr:=pd[i] div 10; //求出对应位相加后的进位
pd[i]:=pd[i] mod 10;
end;
result:='';
count:=e;
while pd[count]=0 do count:=count-1; //去掉结果多余的0
for i:=count downto 1 do result:=result+inttostr(pd[i]) ;

result_edit.Text:= result; //输出结果
end;

(二)超长整数相减
超长整数相减首先要判断被减数和减数的大小,若被减数大于减数,则用被减数减去减数,符号取正,否则用减数减去被减数,符号取负。再把减法转化为对应的数组元素的相减,用第一个数的对应数位数字减去低一位的借位后再与第二个数的对应数位的数字相减,若不够减,则向高位借一位后再减。具体算法如下:
1.判断两个数的大小:
function whoisbigger():integer;
var
flag,count:integer;//flag是大小的标记
begin
if w1>w2 then flag:=1 //若num1的位数比num2的位数大则num1大
else if w1<w2 then flag:=2 //若num1的位数比num2的位数小则num1小
else //若位数相等,则逐位比较,直到不等为止
begin
count:=0;
while (count<=w2) do
begin
if num1[w1-count+1]>num2[w2-count+1] then
begin flag:=1;break; end
else if num1[w1-count+1]<num2[w2-count+1] then
begin flag:=2 ;break; end;
count:=count+1;
end;
if count>w2 then flag:=0 //两个数相等
end;
whoisbigger:=flag;
end;
2.两个数相减
procedure TForm1.sub_btnClick(Sender: TObject);
var

i,cr,count,flag: integer;
result:string;
begin
readnum();
flag:=whoisbigger();
cr := 0;
if flag=0 then result_edit.Text:='0' //两个数相等,结果为0
else begin
if flag=1 then //被减数大于减数,用被减数减去减数,结果为正
begin
result:='';
for i:=1 to w1 do
begin
pd[i]:=num1[i]-cr-num2[i];
if pd[i]<0 then cr:=1 else cr:=0;
pd[i]:=(pd[i]+10) mod 10;
end
end
else //被减数小于减数,用减数减去被减数,结果为负
begin
result:='-';
for i:=1 to w2 do
begin
pd[i]:=num2[i]-cr-num1[i];
if pd[i]<0 then cr:=1 else cr:=0;
pd[i]:=(pd[i]+10) mod 10;
end ;
end;
……;//输出结果
end;
end;

(三)超长整数相乘
两个超长整数相乘采用按位相乘的方法计算,然后把按位乘的结果累加到对应的位上。在实现的过程中关键要弄清楚数组下标的关系。具体算法如下:
procedure TForm1.mul_btnClick(Sender: TObject);
var
i, j, cr,count: integer;
result:string;
begin
readnum();
cr := 0;
for i:=1 to w2 do //两个二进制数各数位相乘
,cr是进位,结果放在数组pd中
if (num2[i]<>0) then
for j:=1 to w1+1 do

begin
pd[i+j-1] := pd[i+j-1] + num2[i]*num1[j] + cr; //按位乘,累加
cr := pd[i+j-1] div 10;
pd[i+j-1] := pd[i+j-1] mod 10;
end;
……;//输出结果
end;

(四)超长整数相除
两个超长整数相除不能用按位相除的方法实现。为此,我们把除法转化为减法,被除数用与除数相同的位数不断地减去除数,每减一次,商就加1,同时更新被除数的数,直到被除数小于除数为止。若被除数的位数还大于除数,重复上述的过程,最后被除数数组中存储的就是两个数相除的余数。如:用6709取除以12,首先用67不断去减12,经过5此减法后,67变成了7,所以第一位商是5。被除数现在变成了709,然后用709去除12,重复上述过程即可。具体算法实现如下:
procedure TForm1.div_btnClick(Sender: TObject);
var
i,cr,count,flag: integer;
result,str:string;
begin
readnum();
flag:=whoisbigger();
if flag=2 then //若被除数小于除数直接输入结果
begin
result_edit.Text:='0';
yushu_edit.Text:=num1_edit.Text;
end
else begin //被除数大于或等于除数
while w2<=w1 do

begin
pd[w1-w2+1]:=pd[w1-w2+1]+1; //商累加
cr:=0;
for i:=1 to w2 do //被除数减去除数
begin
num1[w1-w2+i]:=num1[w1-w2+i]-cr-num2[i];
if num1[w1-w2+i]<0 then cr:=1 else cr:=0;
num1[w1-w2+i]:=(num1[w1-w2+i]+10) mod 10;
end;
count:=0;
while (count<=w2) do //判断被除数减去除数后,做减法的被除数的数与除数的大小
begin
if num1[w1-count+1]>num2[w2-count+1] then
begin flag:=1;break; end
else if num1[w1-count+1]<num2[w2-count+1] then
begin flag:=2 ;break; end;
count:=count+1;
end;
if flag=2 then w1:=w1-1; //做减法的被除数的数小于除数,被除数的数位后移一位
end;

……//输出商
……//输出余数
end;
end;

四、结束语

以上我们实现的是超长整数的基本计算,限于篇幅,我们没有列出对输入的字符的合法性的检查过程。上述实现的过程中,每个数组元素值存储的最大值是9,若我们把每个数组元素存储的最大值改为99或更大,则可以进一步扩大超长整数的存储范围;若我们把进位基数改为其他的数值,我们可以实现任意数制的计算;利用以上的基本运算,还可以帮助我们解决大数分解的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: