2.5 高精度运算

2.5 高精度运算

程序所处理加工的各类数据都有相应的值域限定。一旦某类型的数据超出了规定的范围,运算结果就会出错。下表列举PASCAL内部设置的几种标准类型,其中实数singledoublecompextended为浮点类型,必须在浮点数类型,必须在程序前通过编译命令{$n+}启动浮点数运算后才可使用这些类型。

 

 

 

 

 

类型

值域

 

长度

(以字节为单位)

备注

byte

0…255

1

 

 

标准类型

shortint

-128…128

1

snteger

-32768…32767

2

word

0…65365

2

longint

-2147483648…

2147483647

4

 

 

 

 

real

10-38…1038

6

 

数据处理方式

$ n +

single

1.5*10-45…3.4*1038

4

double

5.0*10-324…1.7*10308

8

comp

-9.2*1018…9.2*1018

8

extENDed

1.9*10-4951…1.1*104932

10

但是在有些试题中,变量运算对象的数值范围是任何数据类型所无法容纳的,因此人们不得不采用数串形式,并将其转化为整数数组,其中每个元素对应一位数,由其下标顺序指明位序号。运算规则如同算术运算。由于高精度运算的结果可能使得数据长度发生增减,因此除需要用整数数组存储数据外,还需要用一个整数变量记录整数数组的元素个数,即数据的实际长度。

2.5.1 高精度加法运算

PROCEDURE  add(a,b;var c);   {a,b,c都为数组,a储存被加数,b储存加数,c储存结果}

VAR  I,x:integer;

BEGIN

 i:=1;

 While (i<=a数组长度>0) or (i<=b数组长度) Do

  Beign

X:=a[I]+b[I]+x div 10;                 {第i位相加并加上上次的进位}

C[I]:=x mod 10;                                  {储存第i位的值}

i:=i+1;                                           {位置指针变量}

end;

 end;

通常,读入的两个整数用可用字符串来储存,程序设计如下:

CONST max200

Var a,b,c:array[1..max] of  0..9

 N:string

 Lena,lenb,lenb,i,x:integer;

Beign

 Write(‘Input augend:’); readln(n);

 Lena:=length(n);

 For i:=1 to lena do a[lena-i+1]:=ord(n[i])-ord(‘0’);

 Write(‘Input addend’); readln(n);

 Lenb:=length(n);

 For i:=1 to lenb do b[lenb-i+1]:=ord(n[i])-ord(‘0’);

 i:=1;

 while (I<=lena) or (i<=lenb) do

  begin

   x:=a[i]+b[i]+x div 10;

   c[i]:=x mod 10 ;

   i:=i+1;

  end;

 if x>=10 then begin lenc:=i;c[i]:=1 end  

         else lenc:=i-1;

for i:=lenc downto 1 do write(c[i]);

writeln;

end. 

2.5.2  高精度减法运算

分析:类似加法,可以用竖式求减法。在做减法运算时,需要注意的是:被减数必须比减数大,同时需要处理借位。因此可以写出如下关系式可以写出如下关系式:

IF a[I]<b[I] THEN BEGIN a[I+1]:=a[I+1]-1;a[i]:=a[i]+10 END

C[I]:=a[I]-b[I]

参考程序

CONST max=200;

Var a,b,c:array[1..max]of 0..9;

  n,n1,n2:string;

lena,lenb,lenc,I,x:integer

begin

  write(‘input minuend:’);readln(n1);

  write(input subtrahend:);readln(n2);                 {处理被减数和减数}

if (length(n1)<length(n2)) or ((length(n1)=length(n2))and (n1<n2))then 

  begin

    n:=n1;n1:=n2;n2:=n;

write(-)                                     n1<n2,结果为负数}                                  

end

lena:=length(n1);lenb:=length(n2);

for I:=1 to lena do a[lena-I+1]:=ord(n1[I])-ord(‘0’);

for I:=1 to lenb do b[lenb-I+1]:=ord(n2[I])-ord(‘0’);

I:=1;

While (I<=lena) or (I<=lenb) do

  Begin

    x:=a[I]-b[I]+10+x ;                       {不考虑大小问题,先往高位借10

    c[I]:=x mod 10 ;                          {保存第I位的值}

    x:=x div 10-1;                            {将高位借到的1减去}  

    I:=I+1;

  End;

Lenc:=I;

While (c[lenc]=0)and (lenc>1) do dec(lenc);          {最高位的0不输出}

For I:=lenc downto 1 do write(c[I]);

Writeln;

End.

2.5.3高精度乘法运算

分析:类似加法,可以用竖式求乘法。在做乘法运算时,同样也有进位,同时对每一位进行乘法运算时,必须进行错位相加。

 

 

 

 

 

 

 

分析C数组下标的变化规律,可以写出如下关系式:

  

由此可见,CA[i]*B[i]乘积有关,跟上次的进位有关,还跟C的位置有关,分析下标规律,有

 x:A[i]*B[i]+x div 10 + C[I+j-1];

 C[I+j-1]:=x mod 10;

const max=200;

var a,b,c:array[1..max]of 0..9;

  n1,n2:string;

  lena,lenb,lenc,i,j,x:integer;

begin

  write('Input multiplier:');readln(n1);

  write('Input nultiplicand:');readln(n2);

  lena:=length(n1);lenb:=length(n2);

  for i:=1 to lena do val(n1[i],a[lena-i+1]);

  for i:=1 to lenb do val(n2[i],b[lenb-i+1]);

  for i:=1 to lena do

    begin

     x:=0;

     for j:=1 to lenb do

      begin                {对乘数的每一位进行处理}

       x:=a[i]*b[j]+x div 10 + c[i+j-1];  {当前乘积+上次乘积进位+原数}

       c[i+j-1]:=x mod 10;

      end;

     c[i+j]:=x div 10;                 {进位}

    end;

  lenc:=i+j;

  while (c[lenc]=0) and(lenc>1) do dec(lenc);

  for i:=lenc downto 1 do write(c[i]);

  writeln;

end.

2.5.4高精度除法运算;

   分析:做除法时,每次上商的值都在09,每次求得的余数连接以后的若干位得到新的被除数,继续做除法。因此,在做高精度除法时,要涉及到乘法和减法运算,还有移位处理。当然,为了程序简洁,可以避免高精度乘法,用0~9次减法取代得到商的值。这里,我们讨论一下高精度数除以单精度数的结果,采取的方法是按位相除法。

〔参考程序〕:

program aa;

  const max=1000;

  var a,c:array[1..max] of 0..9;

      p,z,q,y,x,b:longint;

      n1,n2:string;

      lena:integer;

      code,i,j:integer;

  begin

    readln(n1);

    readln(n2);

    lena:=length(n1);

    for i:=1 to lena do

       a[i]:=ord(n1[i])-ord('0');

    val(n2,b,code); val(n1,y,code);

    x:=0; z:=y div b;   q:=1;i:=1;

    while (y div b)<1 do

      begin

        q:=i; i:=i+1; y:=y*10;

      end;

    for i:=1 to lena do

      begin

        c[i]:=(x*10+a[i]) div b;

        x:=(x*10+a[i]) mod b;

      end;

    for j:= q to 20 do

      begin

        c[j]:=(x*10) div b;

        x:=(x*10) mod b;

      end;

    j:=1;

    while (c[j]=0) and (j<lena) do inc(j);

    i:=1;

    if z<1 then  write(0,'.',c[j])

     else  write(z,'.',c[j]);

    for i:=2 to 20 do  write(c[i]);

    writeln;

 end.

高精度实数的除法

           一、试 题
  编程求解两个高精度正实数的除法。要求精确至小数点后20后,若20位内有循环节,
请标出。
             二、算法分析
  此题的关键不在于如何进行除法, 而在于如何使商精确至小数点后20位。 turbo.
Pascalreal类型只能提供11位十进制数的精度,不可能满足其精度要求。因此,必须像
§2.2高精度实数的减法一样,采用字符串来表示实数,并实现高精度的除法运算。
一、运算前的准备
  首先,我们分别计算出被除数串中后的字符个数J(被除数的小数位数)和除数
串中后的字符个数K(除数的小数位数)。根据被除数和除数同乘(除)一个数,
商不变的法则,分别在两串的尾部添max(J,K)(即被除数和除数同乘10max(J,K)
)使得被除数和除数转换为整数。
  若除数为串,则失败退出。因为0不能被任何数除。
  由于除法是从被除数的高位除起,除数有几位,被除数也要看几位,因此我们在运算前
就设法使被除数的位数大于除数的位数:
  若被除数的串长大于等于除数的串长,则被除数的串首添一个
  若被除数的串长小于除数的串长,则被除数的串首添若干个,使其串长比除数的
串长多出一个字符;
  例如:0.1÷0.003
设 被除数串N1='0.1'; {小数位个数J=1}
除数串N2='0.003'; {小数位个数K=3}
被除数和除数同乘以10max(J,K)(103)
N1='100';
N2='3';
由于N1的串长大于N2的串长,因此
N1='0100';
N2='3';

二、除法运算
  所谓精确至小数点后20位,无非是指(除小数点后的20位前出现循环节或除尽外)
  1、商的小数部分含20位;
  2、对小数点后的21位进行四舍五入;
  为了保证这个精度要求,我们先在被除数串尾添21个。(相当于被除数×10
21。)两数相除后,再在商串的倒数第21个字符前添一个,(相于于商 ÷10
21,)还原商值。
  N1='010000………0'
  └─┬─┘
21
  我们采用试商法进行运算。设K’──除数的串长
  截被除数串的第1..个字符作为余数。若余数值小于除数,则商的第1个字符为
,否则求出满足
C1×除数余数<(C11)×除数
C1C1的数符作为商的第1个字符。(余数-C1×除数)作为第1次除后的余数。然后将被
除数的下一位移至该余数尾。若余数不够减,则商的第2个字符为,否则为满足
  C2×除数余数<(C21)×除数
C2数符,第2次除后的余数=第1次除后的余数-C2×除数,这时可把被除数再下一位移
至余数上,……,这样反复进行,直至全部被除数的位都下移完为止。

        21
┌──┴──┐ 
    00333…………… 3 
  3√01000………………0
009 └──┬──┘
    0010   21个 
0009
00010
00009
00001
……
    ……
    ……

                21个 
┌──┴──┐ 
  N1除以N2后的商串为‘00333…………… 3’
  第一次除,截下被除数的前K个字符作为余数初始值;第二次除的余数为第一次除后
的余数加上从被除数中下移的第K+1个字符……,第i次除的余数为第i-1次除后的
余数加上从被除数中下移的第K+i-1个字符。若被除数串中未下移的字符个数20,
则说明已运算至小数部分,因此,产生一个判断循环小数的问题。
  两数相除判断商是不是循环小数,主要看运算至小数部分后,余数是否重复出现。
  如果余数重复出现,其后所得的商和余数就会出现循环,商就必定重复出现。例如,从
N1÷N2的列竖式计算可以看出,两个重复出现余数10之间的商是3,所以

  N1÷N2='00333'
  接下来的问题是如何输出带有循环小数的商。
  若进入小数运算后的第x次除的余数与进入小数运算后第y次除的余数相等,我们则在商
中循环节的前x位标上小数点;相隔小数点x位的数字上方标上、相隔小数点位的数
字上方标上,表明小数点后的第x位数..y位数是循环小数;然后去除商串头部的无
0


      小数点后第x位 小数点后第y
        │ │
↓←循环小数 → ↓ 
   .
00…00 XX…XX.X…X…………………XX
│ ││ ││ │
└┬┘└┬─┘└────┬───┘
去除 整数部分 小数部分 
无用0
.
例如  N1÷N2='33.3'

  上述算法思想,可以通过一个chu过程来描述:
procedure chu;
begin 21
←' '; ┌┴┐
被除数串被除数串+'0...0';
for i:=除数串长 to 被除数串长 do
begin
{当前余数为被除数的1..i}
if 被除数长度-i≤20(运算到小数部分)
       then begin
if 当前余数与进入小数运算后的某项余数相同
then begin
两个余数间的商为循环节;输出带小数的商;
halt
end {then}
else 存贮当前余数;
end;{then}
求满足
C*除数被除数串中1..i位对应的数值<(C+1)*除数
C;
C数码作为商串的下一个字符;
sub←(C*除数)对应的数串;
被除数中的(i-(sub串长-1))..i位逐位减去sub,使得被除数的前个数码对应当前
余数;
end; {for}
end; {chu}

三、规整商
  若相除的结果未出现循环小数,则必须按如下步骤规整商:
  在商的倒数21位前添入
  删去商的串首的无用
  判断当前余数是否为串:若是,则说明被除数能被除数除尽,依次删去商的串尾
的无用;若尾字符为则为整除,删去;若商串为 ,则原被除数为
0,商置换为
  若余数非串,说明运算至小数点后20位还未除尽。为了保证试题要求的精度,
分析商的尾数符。若大于,则前一位数进一。删去尾数符。
  显然,规整后的商串正好对应问题的解。

             三、程序分析

  下面,我们采用逐步求精的办法给出程序的解。

┏ program chu_fa; 
┃ 一、初始化 
┃ 1.1 定义与说明
┃ begin 
┃ 1.2 init; 
┣ 二、计算 
┃ 2.2 chu; 
┗ 三、输出结果 
3.1 show; 
end. {main} 
第二层
1、求精1.1─定义与说明
var
one,two : string; {被除数(余数),除数}
list : array[1..21] of string;
{list[i]─小数点后第i次相除后的余数(0≤i≤21)}
ans : string; {}
至于函数和过程说明,则在下面逐一给出。
2、求精1.2─init的过程说明
输入被除数串和除数串,并对两串进行规整处理。
procedure init;
var i,j,k : integer;
begin
writeln('Input bei chu shu'); {输入被除数}
readln(one);
writeln('Input chu shu'); {输入除数}
readln(two);
i:=pos('.',one); {确定被除数中'.'的位置}
if i=0 then j:=0 else begin {求被除数的小数位数J并删去'.'}
j:=length(one)-i;
delete(one,i,1);
end; {else}
i:=pos('.',two); {确定除数中'.'的位置}
if i=0 then k:=0 else begin {求除数的小数位置k并删去'.'}
k:=length(two)-i;
delete(two,i,1);
end; {else}
if j>k
then for i:=1 to j-k do two:=two+'0' {被除数和除数化整(同乘10max(j,k)}
else for i:=1 to k-j do one:=one+'0'; 
while (length(two)>0) and (two[1]='0') do delete(two,1,1); 
{去除除数前的多余0}
if two='' then begin {若除数为0,则无解退出}
writeln('no answer!');
halt;
end; {then}
while length(one)<="20" {被除数逐位下移至余数} do length(one) to i:="1" for {为满足精度要求,被除数先乘1021} one:="0" 21 {商串初始化为空} ; ans:="" string; : sub char; c integer; i,j,k,p var chu; procedure 3、求精2.1─ch的过程说明 {init} end; +one; {通过串首添零,使得被除数长度大于除数长度}>0 then begin
2.1.2 out(p,21-(length(one)-i));
{小数点后第P..21-(被除数长度-i)位作为循环节,输出带循环小数的商 ,
并退出程序}
end {then}
else list[21-(length(one)-i)]:=copy(one,1,i);
{list表中未有重复元素,则当前余数存入list}
end; {then}
c:='0'; {商的当前位C初始化为0}
sub:=''; {(C*除数)串初始化为长度与除数相等的'0'}
for j:=1 to length(two) do sub:=sub+'0';
repeat inc(c); {求满足C*除数当前余数<(C+1)*除数的C}
2.1.3 add(sub,two);
2.1.4 until bigger(sub,copy(one,1,i));
dec(c);
sub:='';
for j:=1 to length(two) do sub:=sub+'0';
for j:=1 to ord(c)-ord('0') do add(sub,two);
for j:=length(sub) downto 1 do
{当前余数逐位减去(C*除数)后作为下一次除的余数}
for k:=1 to ord(sub[j])-ord('0') do
2.1.5 minus(i-(length(sub)-j));
ans:=ans+c; {C进入商的当前位}
end; {for}
end; {chu}
4、求精3.1─show的过程说明
对不带循环小数的商先规整处理,然后输出。
procedure show;
var i,j,k : integer;
begin
3.1.1 add_point; {加入小数点}
while (length(ans)>1) and (ans[2]<>'.') and (ans[1]='0')
{删去商串头部的无用0}
do delete(ans,1,1); 
3.1.2 if chu_jing then begin {若除尽,}
while (ans[length(ans)]='0') {删去商串尾部的无用0}
do delete(ans,length(ans),1);
if ans[length(ans)]='.' then delete(ans,length(ans),1);
{若商为整数,则删去商串尾部的'.'}
if ans='' {若商串空,输出商为0,否则输出规整后的结果}
then writeln('0')
else writeln(ans);
end {then}
else begin {若除不尽,}
if ans[length(ans)]>'4' 
{若小数点后第21位的值>4,则前一位值进一}
then inc(ans[length(ans)-1]);
delete(ans,length(ans),1); {删去小数点后第21位并输出商}
writeln(ans);
end; {else}
end; {show}
第三层
1、求精2.1.1─double(copy(one,1,i),21-(length(one)-i))的函数说明
function double(s:string;i:integer):integer;
{输入小数点后第i次相除的余数s。搜索list[1]..list[i-1]。若小数点后第j(1≤j≤i-1)
次相除的余数list[j]s相同,则说明小数点后第j..i位为循环节,返回j;若小数点后的
i次相除的余数各不相同,则返回0}
var j,k : integer;
begin
j:=0; 
repeat inc(j);
until (j>length(s)) or (s[j]<>'0');
if j>length(s) then begin {s'0',返回0}
double:=0;
exit;
end; {then} 
for j:=1 to i-1 do {顺序搜索list[1]..list[i-1]}
begin
k:=1;
while (k<=i-j) and (s[k]='0') do inc(k);
if k>i-j then begin
while (k<=length(s)) and (s[k]=list[j,k-i+j]) do inc(k);
if k>length(s) then begin double:=j; exit; end; {then}
{s[1]··s{i-J}'0'串且s[i-J+1]··s[n]
=List[J,1]··[J,n-i+J], 则返回J}
end; {then}
end; {for}
double:=0;
end; {double}
2、求精2.1.2─out(p,21-(length(one)-i))的过程说明
procedure out(x, y:integer;p:integer);
{小数点后的第x位、第y位分别为循环节的开始和结束,由此得出(商的长度-y) 为小数点
   的位置。该过程将小数点插入该位置,并在小数点后的第x位数字的上方和第y位数字的
上方标两个'.',表明两数之间为循环小数,然后输出带循环小数的商。
var i,j,k : integer;
begin
dec(y);
k:=length(ans)-y+1; {求小数点的位置}
ans:=copy(ans,1,length(ans)-y)+'.'+copy(ans,length(ans)-y+1,y);
{在商的该位置插入小数点}
while (ans[1]='0') and (ans[2]<>'.') do begin {删去商头部的无用0}
delete(ans,1,1);
dec(k);
end;
for i:=1 to k+x-1 do write(' '); {小数点后的第x位上方加'.'}
write('.');
if x=y then begin
writeln;
end {then}
else begin
for i:=1 to y-x-1 do write(' '); {小数点后第y位上方加'.'}
writeln('.');
end; {else}
writeln(ans); {输出带循环小数的商并退出程序}
halt;
end; {out}
3、求精2.1.3──add(sub,two)的过程说明
procedure add(var s,t: string);
{输入两个长整数串st。在进行了s←s+t运算后返回s}
var i,j,p,k : integer;
begin
for i:=length(t) downto 1 do begin {从最低位开始逐位相加}
p:=length(s)-(length(t)-i); {s串中与ti位对应的位数}
for j:=1 to ord(t[i])-ord('0') do begin {对当前位进行累加运算}
k:=p;
while (k>0) and (s[k]='9') do begin {进位}
s[k]:='0';
dec(k);
end; {while}
if k=0 then begin s:='1'+s; inc(p); end
else inc(s[k]);
end; {for}
end; {for}
end; {add}
4、求精2.1.4─bigger(sub,copy)one,1,i)的函数说明
function bigger(s,t:string):boolean;
{比较两个长整数串st的大小。若s>t,则返回true;否则返回false}
var i : integer;
begin
while length(s)length(t) do t:='0'+t;
i:=1; {分别从两串最高位开始,逐位比较}
while (i<=length(s)) and (s[i]=t[i]) do inc(i);
if (i<=length(s)) and (s[i]>t[i])
then bigger:=true
else bigger:=false;
end; {bigger}
5、求精2.1.5─minus(i-(length(sub)-j))的过程说明
procedure minus(i:integer);
{余数的i位减1}
begin
while one[i]='0' do begin one[i]:='9'; dec(i); end; {while}
{若当前位为0,则向高位借位}
dec(one[i]);
end; {minus}
6、求精3.1.1─add_point的过程说明
在商的倒数第21位前加入小数点,还原商。
procedure add_point;
var i,j : integer;
begin
while length(ans)<=21 do ans:='0'+ans;
{通过在商的串首添零,使商的长度>21}
ans:=copy(ans,1,length(ans)-21)+'.'+copy(ans,length(ans)-20,21);
{加入小数点}
end; {add_point}
7、求精3.1.2─chu_jing的函数说明
若两数除尽,返回true,否则返回false
function chu_jing:boolean;
var i,j : integer;
begin
i:=1; {从余数的第1个数符开始逐位分析余数值}
while (i<=length(one)) and (one[i]='0') do inc(i);
if i>length(one) then chu_jing:=true else chu_jing:=false;
{若余数为0,则返回true,否则返回false}
end; {chu_jing}

1用高精度计算算出s=1!+2!+3!+......+n!(n<=50) 输入正整数n输出计算结果s(注意,"高精度计算",不是用普通的整形变量进行运算.

program dfaw; 

type 

auu=array[1..100] of longint; 

var 

a,c:auu; b:longint; len1,len2,len:longint; n:integer; i:integer; 

procedure sar; 

begin 

assign(input,'factor.in'); 

assign(output,'factor.out'); 

reset(input); 

rewrite(output); 

end; 

function cheng(a:auu;b:longint):auu; 

var 

i:longint; 

c:auu; 

begin 

a[1]:=a[1]*b; 

for i:=2 to len1 do 

begin 

a:=a*b+a[i-1]div 10; 

a[i-1]:=a[i-1] mod 10; 

end; 

while a[len1]>=10 do 

begin 

a[len1+1]:=a[len1] div 10; 

a[len1]:=a[len1] mod 10; 

len1:=len1+1; 

end; 

cheng:=a; 

end; 

function jia(a,b:auu):auu; 

var 

i,j:integer; c:auu; 

begin 

fillchar(c,sizeof(c),0); 

if len<len1 then len:=len1; 

for i:=1to len do 

begin 

c:=a+b; 

if c>=10 then 

begin 

c:=c-10; 

c[i+1]:=c[i+1]+1; 

end; 

end; 

if c[len+1]>0 then len:=len+1; 

jia:=c; 

end; 

function jiecheng(x:integer):auu; 

var 

i:integer; c:auu; 

begin 

fillchar(c,sizeof(c),0); 

c[1]:=1; 

for i:=2 to x do 

c:=cheng(c,i); 

jiecheng:=c; 

end; 

begin 

sar; 

fillchar(c,sizeof(c),0); 

len1:=1; len:=1; 

read(n); 

for i:=1 to n do begin 

c:=jia(jiecheng(i),c); len1:=1; end; 

for i:=len downto 1 do write(c); 

close(input); 

close(output); 

end. 

 

program lzj; 

var 

i,j,n:integer; 

a,b:array[1..100001]of integer; 

begin 

read(n); 

a[1]:=1; 

for i:=1to n do 

begin 

j:=1; 

while a[j]<>0 do 

begin 

a[j]:=a[j]*i; 

j:=j+1; 

end; 

j:=1; 

while a[j]<>0 do 

begin 

a[j+1]:=a[j+1]+a[j]div 10; 

a[j]:=a[j]mod 10; 

j:=j+1; 

end; 

j:=1; 

while a[j]<>0 do 

begin 

b[j]:=b[j]+a[j]; 

j:=j+1; 

end; 

j:=1; 

while b[j]<>0 do 

begin 

b[j+1]:=b[j+1]+b[j]div 10; 

b[j]:=b[j]mod 10; 

j:=j+1; 

end; 

end; 

for i:=1to j-1 do 

write(b); 

end. 

算法——高精度加法、减法、乘法、阶乘、除法

    所谓的高精度运算,是指参与运算的数(加数,减数,因子……)范围大大超出了标准数据类型(整型,实型)能表示的范围的运算。例如,求两个200位的数的和。这时,就要用到高精度算法了。在这里,我们先讨论高精度加法。高精度运算主要解决以下三个问题:

基本方法

1、加数、减数、运算结果的输入和存储

运算因子超出了整型、实型能表示的范围,肯定不能直接用一个数的形式来表示。在Pascal中,能表示多个数的数据类型有两种:数组和字符串。

1)数组:每个数组元素存储1位(在优化时,这里是一个重点!),有多少位就需要多少个数组元素;

用数组表示数的优点:每一位都是数的形式,可以直接加减;运算时非常方便

用数组表示数的缺点:数组不能直接输入;输入时每两位数之间必须有分隔符,不符合数值的输入习惯;

2)字符串:字符串的最大长度是255,可以表示255位。

用字符串表示数的优点:能直接输入输出,输入时,每两位数之间不必分隔符,符合数值的输入习惯;

用字符串表示数的缺点:字符串中的每一位是一个字符,不能直接进行运算,必须先将它转化为数值再进行运算;运算时非常不方便;

3)因此,综合以上所述,对上面两种数据结构取长补短:用字符串读入数据,用数组存储数据:

var s1,s2 : string;

a,b,c : array [1..260] of integer;

i,l,k1,k2 : integer;

begin

write('input s1:');readln(s1);

write('input s2:');readln(s2);

{————读入两个数s1s2,都是字符串类型}

l:=length(s1);{求出s1的长度,也即s1的位数;有关字符串的知识。}

k1:=260;

for i:=l downto 1 do

begin

a[k1]:=ord(s1[ i ])-48;{将字符转成数值}

k1:=k1-1; 

end; 

k1:=k1+1;

{————以上将s1中的字符一位一位地转成数值并存在数组a中;低位在后(从第260位开始),高位在前(每存完一位,k11

 对s2的转化过程和上面一模一样。

2、运算过程

在往下看之前,大家先列竖式计算35+86

注意的问题:

1)运算顺序:两个数靠右对齐;从低位向高位运算;先计算低位再计算高位;

2)运算规则:同一位的两个数相加再加上从低位来的进位,成为该位的和;这个和去掉向高位的进位就成为该位的值;如上例:3+8+1=12,向前一位进1,本位的值是2;可借助MODDIV运算完成这一步;

3)最后一位的进位:如果完成两个数的相加后,进位位值不为0,则应添加一位;

4)如果两个加数位数不一样多,则按位数多的一个进行计算;

if k1>k2 then k:=k1 else k:=k2;

y:=0;

for i:=260 downto k do

begin

x:=a[ i ]+b[ i ]+y;

c[ i ]:=x mod 10;

y:=x div 10;

end; 

if y<>0 then begin k:=k-1;c[k]:=y; end;

3、结果的输出(这也是优化的一个重点)

按运算结果的实际位数输出

for i:=k to 260 do write(c[ i ]);

writeln; 

4、例子:求两个数的加法

program sum;

var s,s1,s2 : string;

a,b,c : array [1..260] of integer;

i,l,k1,k2 : integer;

begin

write('input s1:');readln(s1);

write('input s2:');readln(s2);

l:=length(s1);

k1:=260;

for i:=l downto 1 do

begin

a[k1]:=ord(s1[ i ])-48;

k1:=k1-1; 

end; 

k1:=k1+1;

l:=length(s2);

k2:=260;

for i:=l downto 1 do

begin

b[k2]:=ord(s2[ i ])-48;

k2:=k2-1; 

end; 

k2:=k2+1; 

if k1>k2 then k:=k2 else k:=k1;

y:=0;

for i:=260 downto k do

begin

x:=a[ i ]+b[ i ]+y;

c[ i ]:=x mod 10;

y:=x div 10;

end;

if y<>0 then begin k:=k-1;c[k]:=y; 

end;

for i:=k to 260 do write(c[ i ]);

writeln; 

end. 

优化:

以上的方法的有明显的缺点:

1)浪费空间:一个整型变量(-32768~32767)只存放一位(0~9);

2)浪费时间:一次加减只处理一位;

针对以上问题,我们做如下优化:一个数组元素存放四位数;(integer的最大范围是327675位的话可能导致出界)。具体方法:

l:=length(s1);

k1:=260;

repeat {————有关字符串的知识}

s:=copy(s1,l-3,4);

val(s,a[k1],code);

k1:=k1-1; 

s1:=copy(s1,1,l-4);

l:=l-4; 

until l<=0;

k1:=k1+1;

而因为这个改进,算法要相应改变:

1)运算时:不再逢十进位,而是逢万进位(mod 10000; div 10000);

2)输出时:最高位直接输出,其余各位,要判断是否足够4位,不足部分要补0;例如:1232345这样三段的数,输出时,应该是100232345而不是1234567

改进后的算法:

program sum;

var s1,s2 : string;

a,b,c : array [1..260] of integer;

i,l,k1,k2,code : integer;

begin

write('input s1:');readln(s1);

write('input s2:');readln(s2);

l:=length(s1);

k1:=260;

repeat {————有关字符串的知识}

s:=copy(s1,l-3,4);

val(s,a[k1],code);

k1:=k1-1; 

s1:=copy(s1,1,l-4);

l:=l-4; 

until l<=0;

k1:=k1+1;

l:=length(s2);

k2:=260;

repeat

s:=copy(s2,l-3,4);

val(s,b[k2],code);

k2:=k2-1; 

s2:=copy(s2,1,l-4);

l:=l-4; 

until l<=0; 

k2:=k2+1; 

if k1<k2 then k:=k1 else k:=k2;

y:=0;

for i:=260 downto k do

begin

x:=a[ i ]+b[ i ]+y;

c[ i ]:=x mod 10000;

y:=x div 10000;

end;

if y<>0 then begin k:=k-1;c[k]:=y;end; 

write(c[k]);

for i:=k+1 to 260 do

begin 

if c[ i ]<1000 then write('0');

if c[ i ]<100 then write('0');

if c[ i ]<10 then write('0');

write(c[ i ]); 

end;

writeln; 

end.

高精度算法

在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字.¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,,,,乘方,阶乘,开放等运算.¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  譬如一个很大的数字N >= 10^ 100, 很显然这样的数字无法在计算机中正常存储.¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  于是我们想到了办法,将这个数字拆开,拆成一位一位的 或者是四位四位的存储到一个数组中用一个数组去表示一个数字.这样这个数字就被称谓是高精度数.¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  对于高精度数,也要像平常数一样做加减乘除以及乘方的运算,于是就有了高精度算法:¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  下面提供了Pascal的高精度加法高精度乘以单精度高精度乘以高精度的代码其他版本请各位大牛添加进来吧!¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Pascal代码如下(非完整); k为预定进制,加大进制以提高速度。¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Procedure HPule(a, b: Arr; Var c:Arr); //高精度加法¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Var¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  i: Integer;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  FillChar(c, SizeOf(c), 0);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  For i:= 1 To Maxn-1 Do Begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci:= ci] + ai] + bi;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci + 1] := ci] Div k;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci] := ci] Mod k¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  End;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  End;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Procedure HPule(a: Arr; b:Integer; Var c:Arr); //高精度乘以单精度¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Var¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  i: Integer;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  FillChar(c, SizeOf(c), 0);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  For i:= 1 To Maxn-1 Do Begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci] := ci] + ai] * b;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci+1:= ci] Div k;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci:= ci] Mod k¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  End;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  End;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Procedure HPule(a, b: Arr; ; Var c:Arr); //高精度乘以高精度¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Var¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  i, j: Integer;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  FillChar(c, SizeOf(c), 0);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  For i:= 1 To Maxn Do ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  For j := 1 To Maxn Begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci+j-1] := ci+j-1] + ai] * b[j];¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci+j]:= ci+j-1] Div k;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  ci+j-1:= ci+j-1] Mod k¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  End;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  End;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  Ps:为了防止百度错误识别过程中有不少符号是全角状态输入.¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  高精度加法¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  var ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  a,b,c:array[1..201] of 0..9;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  n:string;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  lena,lenb,lenc,i,x:integer;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write('Input augend:'); readln(n);lena:=length(n); ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=1 to lena do a[lena-i+1]:=ord(n)-ord('0');{加数放入a数组}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write('Input addend:'); readln(n); lenb:=length(n); ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=1 to lenb do b[lenb-i+1]:=ord(n)-ord('0');{被加数放入b数组}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  i:=1;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  while (i<=lena) or(i<=lenb) do¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x := a + b + x div 10; {两数相加,然后加前次进位}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  c := x mod 10; {保存第i位的值}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  i := i + 1¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  if x>=10 {处理最高进位}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  then begin lenc:=i; c:=1 end ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  else lenc:=i-1;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=lenc downto 1 do write(c); writeln {输出结果}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end. ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  高精度乘法(低对高)¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  const max=100; n=20;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  var a:array[1..max]of 0..9;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  i,j,k;x:integer;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  k:=1; a[k]:=1;{a=1}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=2 to n do{a*2*3….*n} ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x:=0;{进位初始化}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for j:=1 do k do{a=a*i}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x:=x+a[j]*i; a[j]:=x mod 10;x:=x div 10¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  while x>0 do {处理最高位的进位}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  k:=k+1;a[k]:=x mod 10;x:=x div 10¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  writeln;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=k dowento 1 write(a){输出a}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end.¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  高精度乘法(高对高)¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  var a,b,c:array[1..200] of 0..9;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  n1,n2:string; lena,lenb,lenc,i,j,x:integer;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write('Input multiplier:'); readln(n1);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  rite('Input multiplicand:'); readln(n2);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  lena:=length(n1); lenb:=length(n2);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=1 to lena do a[lena-i+1]:=ord(n1)-ord('0');¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=1 to lenb do b[lenb-i+1]:=ord(n2)-ord('0');¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=1 to lena do ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x:=0; ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for j:=1 to lenb do{对乘数的每一位进行处理}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x := a*b[j]+x div 10+c;{当前乘积+上次乘积进位+原数¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  c:=x mod 10;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  c:= x div 10;{进位}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  lenc:=i+j;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  while (c[lenc]=0) and (lenc>1) do dec(lenc); {最高位的0不输出}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i:=lenc downto 1 do write(c); writeln¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end. ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  高精度除法¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  fillchar(s,sizeof(s),0);{小数部分初始化}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  fillchar(posi,sizeof(posi),0); {小数值的位序列初始化}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  len←0;st←0; {小数部分的指针和循环节的首指针初始化}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  read(x,y);{读被除数和除数}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write(x div y);{输出整数部分}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x←x mod y;{计算x除以y的余数}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  if x=0 then exit;{x除尽y,则成功退出}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  while len<limit do{若小数位未达到上限,则循环}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  inc(len);posi[x]←len;{记下当前位小数,计算下一位小数和余数}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  x←x*10; s[len]←x div y;x←x mod y;¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  if posi[x]<>0 {若下一位余数先前出现过,则先前出现的位置为循环节的开始}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  then begin st←posi[x]; break;end;{then}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  if x=0 then break; {若除尽,则成功退出}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;{while}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  if len=0 ¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  then begin writeln;exit;end;{若小数部分的位数为0,则成功退出;否则输出小数点}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write('.');¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  if st=0 {若无循环节,则输出小数部分,否则输出循环节前的小数和循环节}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  then for i←1 to len do write(s)¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  else begin¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i←1 to st-1 do write(s);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write('(');¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  for i←st to len do write(s);¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  write(')');¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q
  end;{else}¸v¸ÚËÞßx\www.ntrj.net39Ä}‡Š%†Q 

 

 

 

 

 

 

 

 

 

 

posted @ 2010-10-11 21:31  lj_cherish  阅读(775)  评论(0编辑  收藏  举报