- 注册时间
- 2008-7-21
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 11556
- 在线时间
- 小时
|
楼主 |
发表于 2009-2-25 11:01:16
|
显示全部楼层
扩大进制数改善高精度运算效率
用整数数组每一个元素表示一个十进制整数的方法存在的缺点是:如果十进制的位数很多,则对应的数组的长度会很长,并增加了高精度计算的时间。
如果用一个元素记录2位数字、3位数字或更多位数字,则数组的长度可以明显缩小,但是还要考虑数的取值范围问题,必须保证程序运行过程中不越界。在权衡了两方面的情况后得出:用一个longint记录4位数字是最佳的方案。那么这个数组就相当于一个10000进制的数,其中每一个元素都是10000进制下的一位数。-
- 一、数据类型定义:type
- numtype=array[1..10000] of longint; {可以存储40000位十进制数}
- var
- a,n:numtype;
- la,ln:byte;
- s:ansistring; {任意长度的字符串类型}
复制代码 二、整数数组的建立和输出- readln(s);
- k:=length(s);
- for i:=1 to k do
- begin
- j:=(k-i+4) div 4;
- n[j]:=n[j]*10+ord(s[i])-48;
- end;
- ln:=(k+3) div 4;
-
- 当得出最后结果n后,必须按照次高位到最低位的顺序,将每一位元素由10000进制数转换成十进制数,即必须保证每个元素对应4位十进制数。例如n[i]=0015(0<=i<=ln-2),对应的十进制数不能为15,否则会导致错误结果。可以按照如下方法输出n对应的十进制数:[code]write(n[ln]);
- for i:=ln-1 downto 1 do
- write(n[i] div 1000,(n[i] div 100) mod 10,(n[i] div 10) mod 10,n[i] mod 10);
-
- 三、基本运算
- 两个10000进制整数的加法和减法与前面的十进制运算方法类似,只是进制变成了10000进制。
- 1、整数数组减1(n:=n-1,n为整数数组)
- 从n[1]出发寻找第一个非零的元素,由于接受了低位的借位,因此减1,其后缀全为9999。如果最高位为0,则n的长度减1。
- j:=1;
- while (n[j]=0) do inc(j); {寻找第一个非零的元素}
- dec(n[j]); {该位接受低位的借位,因此减1}
- for i:=1 to j-1 do
- n[i]:=9999; {其后缀全为9999}
- if (j=ln) and (n[j]=0) {如果最高位为0,则n的长度减1}
- then dec(ln);
-
- 2、整数数组除以整数(a:=a div i,a为整数数组,i为整数)
- 按照从高位到低位的顺序,逐位相除,把余数乘进制后加到下一位继续相除。如果最高位为0,则a的长度减1。
- l:=0;
- for j:=la downto 1 do
- begin
- inc(a[j],l*10000);
- l:=a[j] mod i;
- a[j]:=a[j] div i;
- end;
- while a[la]=0 do dec(la);3、两个整数数组相乘(a:=a*n,a和n为整数数组)
- 按照从高位到低位的顺序,将数组a的每一个元素与n相乘。[code]procedure multiply(a,b:numtype;la,lb:longint;var s:numtype;var ls:longint);
- var
- i,j:longint;
- begin
- for i:=1 to la do
- for j:=1 to lb do
- s[i+j-1]:=s[i+j-1]+a[i]*b[j];
- for i:=1 to la+lb-1 do
- begin
- s[i+1]:=s[i+1]+s[i] div 10000;
- s[i]:=s[i] mod 10000;
- end;
- if s[la+lb]=0
- then ls:=la+lb-1
- else ls:=la+lb;
- end;
复制代码
[ 本帖最后由 kon3155 于 2009-2-25 13:11 编辑 ] |
|