zoukankan      html  css  js  c++  java
  • 超长整型数据的四则运算转

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

     

     

    [参考文献]

     

    [1] 杨志刚等.Delphi 5.0 程序设计[M].北京:中国铁道出版社,2000.

    [2] (美)Marco Cantu .Delphi 6从入门到精通[M].王辉等译.北京:电子工业出版社,2002.

    [3] 阶梯创作室.Delphi 6高级编程技术[M].北京:中国水利水电出版社,2002.

    [4] 段兴,唐一丁等.Delphi实用程序100例[M].北京:人民邮电出版社,2002.

    [5] 谢柏青, 佘晓歌.算法与数据结构[M].北京:高等教育出版社,2001.

     

       

    The   Achievement of Arithmetic Problems on Long Integer Basing on Dephi

     

    Gong Cheng-qing

     

    (Dept. of Computers, Guangdong Women’s Professional Technical College, Guangzhou 511450China )

     

     

    Abstract:This thesis use the array to save long integer.It turns the computation on long integer into the computation on the element of array.In this way,it completes the   Arithmetic Problems on Long Integer.

    Key word: Long Integer;array; computation

    收稿日期:2004-12-30

    作者简介:龚成清(1979- ),男,广东增城人,理学学士,广东女子职业技术学院计算机系助理讲师,从要从事计算机软件的教学和开发研究。

  • 相关阅读:
    SMI/慧荣/SM32**主控量产通用教程,PNY U盘量产!
    显示隐藏文件的批处理!
    office2003与office2007/2010文件关联问题!
    WDS功能及中继与桥接模式的区别.
    利用WinRar命令行定时备份Sql2005数据库!
    windows 7 关机的误区及睡眠和休眠的作用。
    ajax helloworld jsp ajax入门,后台使用jsp
    jquery width height innerWidth innerHeight
    d3.js GeoJSON 显示陕西省地图 projection
    jquery 向html添加元素append prepend before after
  • 原文地址:https://www.cnblogs.com/wangyuanf/p/2595576.html
Copyright © 2011-2022 走看看