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

基于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; //num1num2两个数组分别存储两个超长整数,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, crcount: 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或更大,则可以进一步扩大超长整数的存储范围;若我们把进位基数改为其他的数值,我们可以实现任意数制的计算;利用以上的基本运算,还可以帮助我们解决大数分解的问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值