怎么进行高精度负数和正数的运算运算

高精度计算
一:高精度正整数加法计算。
例1.从键盘上读入两个100位长的正整数,编程求出它们的和。
[分析]:TurboPascal中整数的范围是-,显然是不够表示出100位长的正整数的,而实数的范围虽然可以达到10-38-1038,但是它的有效数字只有11位,也不能满足题目的要求,为此我们可以考虑使用字符串或者是整数数组来表示一个唱的正整数。用字符串来表示数在输入和输出时是要容易些,而用数组表示则在计算时要容易理解一些。
这里我们用字符串表示正整数,通过字符串输入加数和被加数,假设分别是s1=’3210’和s2=’98765’,先来看一看人手工是怎么加的:
1. 因为两个加数长度不一样,所以要在较短的加数前添上0使长度一致。这样s1=’03210’,s2=’98765’;
2. 按照加法的原则从低位向高位加:
a) 先算5+0,得5,在和的对应位上写5;
b) 再算1+6,得7,在和的相应位上写7;
c) 再算2+7,得9,在和的相应位上写9;
d) 再算3+8,得11,在和的相应位上写1,并向前面进位1;
e) 再算0+9,加上刚才的进位,得10,在和的相应位上写0;
3. 最后还有一个进位1,加在和的前面;
4. 计算完成,输出结果101975
从计算步骤中我们看到计算两个加数的和主要要考虑对位,相加,进位三个方面:
考虑对位时只要比较两个加数的长度,在较短的加数前添上适当的零就可以了;
l1:=length(s1);l2:=length(s2);
if l1&l2 then for i:=1 to l1-l2 do s2:=’0’+s2
else for i:=1 to l2-l1 do s1:=’0’+s1;
考虑加法是要注意到读入的是字符,是不能够直接进行加运算的,但是因为字符’0’-‘9’在ASCII表中是连续的,数字0-9在数学中也是连续的,所以它们有一定的关系,这个关系就是ord函数和chr函数,所以可以通过式子ord(ch)-ord('0')将字符ch转换成对应的数字再计算,计算完后再通过表达式chr(ord('0')+k)将数字k转成对应的字符。当然此时’0’≤ch≤‘9’,0≤k≤9。
至于进位,可以设置一个进位标记,计算前先置为0,若计算结果大于9,处理进位,置进位为1,当前结果减10,否则置位0,
处理某位的加和进位的代码段位为:
k:=ord(s1[i])-ord('0')+ord(s2[i])-ord('0'); {当前两位相加}
k:=k+j; {加上上次的进位}
if k&9 then begin j:=1 ;k:=k-10 end else j:=0;
{新的进位设置}
s3:=chr(ord('0')+k)+s3; {将数字还原成字符写入和的当前位}
其中j是进位标记,s3是和,k是当前位的和。
只要从最后一位依次往前处理各位的加和进位就可以实现这个加法过程,当然在第一位处理完了后在判断一下是否有进位。
s1,s2,s3 : {用字符串表示加数、被加数和和}
l1,l2 : {加数和被加数的位数(长度)}
readln(s1);readln(s2);
l1:=length(s1);l2:=length(s2);
if l1&l2 then
for i:=1 to l1-l2 do s2:='0'+s2
for i:=1 to l2-l1 do s1:='0'+s1;
{在比较短的加数前添上0}
j:=0;s3:=''; {初始时设置无进位,和为0}
for i:=length(s1) downto 1 do {从低位到高位加}
k:=ord(s1[i])-ord('0')+ord(s2[i])-ord('0')+j;
if k&9 then begin j:=1 ;k:=k-10 end else j:=0;
s3:=chr(ord('0')+k)+s3; {将次位加到S3的前面}
{逐位加法计算}
if j=1 then s3:='1'+s3; {最高位的进位}
writeln(s3);
二:高精度正实数加法计算。
例2.从键盘上读入两个100位长的正实数,编程求出它们的和。
[分析]:与上例不同,我们这次考要考虑的是实数问题,即小数点的问题,我们按照小学数学中的带小数的数的加法规则,应该先对齐小数点,然后实施加法,所以可以先对齐小数点,然后删除小数点实施整数加法,最后还原小数点。
对于最后的结果,还要进行规格化:小数最后的零应该省去。
这里我们用逐步求精的方法给出程序:
program 正实数加法
1-1:以字符串的形式读入两个实数;
1-2:对齐小数点和各相应数位;
1-3:记录小数点的位置,删除加数和被加数中的小数点;
1-4:按照整数加法求出和;
1-5:还原小数点;
1-6:规格输出结果。
1-2:对齐小数点和各相应数位部分的求精
1-2-1:根据小数点的位置判断是否是整数,若是整数则在最后添上小数点;
1-2-2:分别记录加数和被加数小数点的位置和整数部分、小数部分的长度;
1-2-3:在整数部分较短的数前面添零,在小数部分较短的数后面添零对齐各相应数位;
1-2-4:重新记录小数点的位置,即整数部分的长度。
1-6:规格输出结果部分的求精:
1-6-1:最后一位是零则删除最后一位;
1-6-2:若小数部分被删除玩,即最后一位是小数点则删除小数点。
按照以上的逐步求精,编制程序如下:
s1,s2,s3 : {用字符串表示加数、被加数和和}
l1,l2 : {加数和被加数的位数(长度)}
z1,z2,x1,x2 : {加数和被加数的整数部分和小数部分的位数(长度)}
pointpos : {小数点的位置}
readln(s1);readln(s2);
k:=pos('.',s1);if k=0 then s1:=s1+'.';
k:=pos('.',s2);if k=0 then s2:=s2+'.'; {添上小数点}
l1:=length(s1);k:=pos('.',s1); z1:=k-1;x1:=l1-k;
l2:=length(s2);k:=pos('.',s2); z2:=k-1;x2:=l2-k; {记录小数点的位置}
if z1&z2 then {整数部分对齐}
for k:=1 to z1-z2 do s2:='0'+s2
for k:=1 to z2-z1 do s1:='0'+s1;
if x1&x2 then {小数部分对齐}
for k:=1 to x1-x2 do s2:=s2+'0'
for k:=1 to x2-x1 do s1:=s1+'0';
k:=pos('.',s1);delete(s1,k,1);delete(s2,k,1);s3:=s1;pointpos:=k;
{删除小数点}
for i:=length(s3) downto 1 do
k:=ord(s1[i])-ord('0')+ord(s2[i])-ord('0')+j;
if k&9 then begin j:=1 ;k:=k-10 end else j:=0;
s3[i]:=chr(ord('0')+k);
{逐位加法计算}
if j=1 then
s3:='1'+s3; {最高位的进位}
pointpos:=pointpos+1;
insert('.',s3,pointpos); {还原小数点}
while s3[length(s3)]='0' do delete (s3,length(s3),1);
{删除小数部分末尾的零}
if s3[length(s3)]='.' then delete (s3,length(s3),1);
{根据条件删除小数点}
writeln(s3);
三:高精度正整数乘法计算。
例3.计算50!的精确值。其中50!=1*2*3*4……*50。
50!是个很大的数字,通过数学计算我们知道它的值大约在左右,显然用TurboPascal的实数和整数都是不能存储的,还是得使用高精度计算。
这个问题的情况比较特殊,参与乘法的两个乘数一个是高精度数,另一个是常规的整数,为此我们采用整数数组去存储结果。
这里还是以12!=12*11!=12*为例说明这个计算过程:
a数组存放的是上一次阶乘的结果,因为这个乘积最大可能是,我们定义a为array[1..100] of
integer,所以此时a数组的存放情况为:
I 1 2 3 4 5 6 7 8 9 10 …… 98 99 100
A[i] 0 0 8 6 1 9 9 3 0 0 …… 0 0 0
在进行计算时将a中的各个元素分别同乘数相乘,结果存放在当前位,上面的a数组同12相乘,得到的中间结果为:
I 1 2 3 4 5 6 7 8 9 10 …… 98 99 100
12*a[i] 0 0 96 72 12 108 108 36 0 0 …… 0 0 0
实现相乘的程序段很简单: for j:=1 to 100 do a[j]:=a[j]*i;
为了避免多次乘积时将乘积累乘至很大的数造成溢出,每次乘积运算之后将处理进位,进位的方法同加法,但是有进多位的可能。上例中a[3]将向a[4]进位9,进位后a[3]=6,a[4]=81,同时a[4]在向a[5]进位9,进位后a[4]=1,a[5]=20……
下面的程序段可以实现这个进位处理:
for j:=1 to 100 do
k:=a[j]; {事先复制a[j]保存}
a[j]:=k mod 10; {最后一位留下}
a[j+1]:=a[j+1]+k div 10; {上一位接受进位}
实施进位处理后的a数组为:
I 1 2 3 4 5 6 7 8 9 10 …… 98 99 100
a[i] 0 0 6 1 0 0 9 7 4 0 …… 0 0 0
这同我们手工计算的12!=是一样的。
a:array[0..100]
a[0]:=1;for i:=1 to 100 do a[i]:=0;a[0]:=1;
for i:=2 to 50 do
for j:=0 to 100 do a[j]:=a[j]*i;
for j:=0 to 100 do
a[j]:=k mod 10;
a[j+1]:=a[j+1]+k div 10;
j:=100;while a[j]=0 do j:=j-1;
write('50!=');
for i:=j downto 0 do write(a[i]);
在这个程序中我们使用了100位的数组存放中间结果,但是对于大部分的情况都不会用到100位,前面的零都是不必要进行乘法运算的,我们可以考虑使用一个数值记录当前被乘数的有效位数,即自右向左非零数的个数。
这样可以省略很多无益的计算,大大提高计算效率。
例4.从键盘输入两个100位长的正整数,编程求出它们的乘积。
[分析]:跟上面的高精度整数加法一样,我们同样先来手算一个具体的例子:s=1234*56,仍采用整数数组来存放,其中a数组表示被乘数,有效位4位,其中a[0]=4,a[1]=3,a[2]=2,a[3]=1,所表示的数为:a[0]*100+a[1]*101+a[2]*102+a[3]*103;b数组表示乘数,有效位3位,其中b[0]=6,b[1]=5,所表示的数为:b[0]*100+b[1]*101,若用c数组表示乘积,根据多项式乘法数学知识:c[0]的值应该是a[0]和b[0]的乘积的个位数,c[1]的值应该是a[1]与b[0]的乘积,a[0]与b[1]的乘积,c[0]向前的进位三者之和,若象上面例子一样先不考虑进位留待最后一次处理进位,则:
c[0]=a[0]*b[0];
c[1]=a[1]*b[0]+a[0]*b[1]
c[2]=a[2]*b[0]+ a[1]*b[1]+ a[0]*b[2]
for i:=0 to la do
for j:=0 to lb do
c[i+j]:=c[i+j]+a[i]*b[j];
a位整数和b位整数的乘积位数应该是a+b-1或者a+b位,小学数学中的乘法的竖式如下:
在这个竖式中我们一边乘法一边处理了进位,其实可以先处理一位数的乘法,最后在相加时一起处理进位,即计算如下:
a,b,c : array[0..100]
readln(s1);readln(s2);
la:=length(s1);lb:=length(s2);lc:=la+
for i:=la-1 downto 0 do a[i]:=ord(s1[la-i])-ord('0');
for i:=lb-1 downto 0 do b[i]:=ord(s2[lb-i])-ord('0');;
for i:=lc downto 0 do c[i]:=0;
for i:=0 to la do
for j:=0 to lb do
c[i+j]:=c[i+j]+a[i]*b[j];
for i:=0 to lc do
c[i]:=c[i]+k;
k:=c[i] div 10;
c[i]:=c[i] mod 10;
if c[lc]=0 then lc:=lc-1;
for i:=lc-1 downto 0 do write(c[i]);
四所谓的高精度运算,是指参与运算的数(加数,减数,因子……)范围大大超出了标准数据类型(整型,实型)能表示的范围的运算。例如,求两个200位的数的和。这时,就要用到高精度算法了。在这里,我们首先讨论高精度加法。
[编辑本段]高精度加法
  高精度运算主要解决以下三个问题:
  一、加数、减数、运算结果的输入和存储
  运算因子超出了整型、实型能表示的范围,肯定不能直接用一个数的形式来表示。在Pascal中,能表示多个数的数据类型有两种:数组和字符串。
  数组:每个数组元素存储1位(在优化时,这里是一个重点!),有多少位就需要多少个数组元素;用数组表示数的优点:每一位都是数的形式,可以直接加减;运算时非常方便。用数组表示数的缺点:数组不能直接输入;输入时每两位数之间必须有分隔符,不符合数值的输入习惯;
  字符串:String型字符串的最大长度是255,可以表示255位。Ansistring型字符串长度不受限制。用字符串表示数的优点:能直接输入输出,输入时,每两位数之间不必分隔符,符合数值的输入习惯;用字符串表示数的缺点:字符串中的每一位是一个字符,不能直接进行运算,必须先将它转化为数值再进行运算;运算时非常不方便;
  综合以上所述,对上面两种数据结构取长补短:用字符串读入数据,用数组存储数据:
  var s1,s2:
  a,b,c:array [1..260]
  i,l,k1,k2:
  write('input s1:');readln(s1);
  write('input s2:');readln(s2);
  {————读入两个数s1,s2,都是字符串类型}
  l:=length(s1);{求出s1的长度,也即s1的位数;有关字符串的知识。}
  k1:=260;
  for i:=l downto 1 do
  a[k1]:=ord(s1)-48;{将字符转成数值}
  k1:=k1-1;
  k1:=k1+1;
  {————以上将s1中的字符一位一位地转成数值并存在数组a中;低位在后(从第260位开始),高位在前(每存完一位,k1减1),完后,k1指向最高位}
  对s2的转化过程和上面一模一样。
  二、运算过程
  在往下看之前,大家先列竖式计算35+86。
  注意的问题:
  (1)运算顺序:两个数靠右对齐;从低位向高位运算;先计算低位再计算高位;
  (2)运算规则:同一位的两个数相加再加上从低位来的进位,成为该位的和;这个和去掉向高位的进位就成为该位的值;如上例:3+8+1=12,向前一位进1,本位的值是2;可借助MOD、DIV运算完成这一步;
  (3)最后一位的进位:如果完成两个数的相加后,进位位值不为0,则应添加一位;
  (4)如果两个加数位数不一样多,则按位数多的一个进行计算;
  if k1&k2 then k:=k1 else k:=k2;
  for i:=260 downto k do
  x:=a+b+y;
  c:=x mod 10;
  y:=x div 10;
  if y&&0 then begin k:=k-1;c[k]:=y;
  三、结果的输出(这也是优化的一个重点)
  按运算结果的实际位数输出
  for i:=k to 260 do write(c);
  例子:求两个数的加法
  var s,s1,s2:
  a,b,c:array [1..260]
  i,l,k1,k2:
  write('input s1:');readln(s1);
  write('input s2:');readln(s2);
  l:=length(s1);
  k1:=260;
  for i:=l downto 1 do
  a[k1]:=ord(s1)-48;
  k1:=k1-1;
  k1:=k1+1;
  l:=length(s2);
  k2:=260;
  for i:=l downto 1 do
  b[k2]:=ord(s2)-48;
  k2:=k2-1;
  k2:=k2+1;
  if k1&k2
  then k:=k2
  else k:=k1;
  for i:=260 downto k do
  x:=a+b+y;
  c:=x mod 10;
  y:=x div 10;
  if y&&0
  k:=k-1;
  c[k]:=y;
  for i:=k to 260 do write(c);
四、优化:
  以上的方法的有明显的缺点:
  (1)浪费空间:一个整型变量(-)只存放一位(0~9);
  (2)浪费时间:一次加减只处理一位;
  针对以上问题,我们做如下优化:一个数组元素存放四位数;(integer的最大范围是32767,5位的话可能导致出界)将标准数组改为紧缩数组。第一步的具体方法:
  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;例如:1,23,2345这样三段的数,输出时,应该是而不是1232345。
  改进后的算法:
  var s1,s2,s:
  a,b,c:packed array [1..260]
  i,l,k1,k2,code:
  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;
  for i:=260 downto k do
  x:=a+b+y;
  c:=x mod 10000;
  y:=x div 10000;
  if y&&0 then begin
k:=k-1;c[k]:=y;
  write(c[k]);
  for i:=k+1 to 260 do
  if c&1000 then write('0');
  if c&100 then write('0');
  if c&10 then write('0');
  write(c);
[编辑本段]高精度减法
  减法:和高精度加法相比,减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。
  2、算法流程:
  (1)读入被减数S1,S2(字符串);
  (2)置符号位:判断被减数是否大于减数:大则将符号位置为空;小则将符号位置为“-”,交换减数与被减数;
  (3)被减数与减数处理成数值,放在数组中;
  (4)运算:
  A、取数;
  B、判断是否需要借位;
  C、减,将运算结果放到差数组相应位中;
  D、判断是否运算完成:是,转5;不是,转A;
  (5)打印结果:符号位,第1位,循环处理第2到最后一位;
  3、细节:
  ▲如何判断被减数与减数的大小:字符串知识
  (1)首先将两个字符串的位数补成一样(因为字符串的比较是从左边对齐的;两个字符串一样长才能真正地比较出大小):短的在左边补0
  k1:=length(s1);
  k2:=length(s2);
  if k1&k2 then for i:=1 to k1-k2 do
s2:='0'+s2
  else for i:=1 to k2-k1 do s1:='0'+s1;
  (2)接着比较大小:直接比较字符串大小
  fh:='';
  if s1&s2 then begin fh:='-';s:=s1; s1:=s2; s2:=s;
  {————s1存被减数,fh存符号}
  ▲将字符串处理成数值:
  l:=length(s1);{求出s1的长度,也即s1的位数;有关字符串的知识。}
  k1:=260;
  for i:=l downto 1 do
  a[k1]:=ord(s1)-48;{将字符转成数值}
  k1:=k1-1;
  k1:=k1+1;
  ▲运算(减法跟加法比较,减法退位处理跟加法进位处理不一样):
  a.处理退位;
  跟加法一样,在for语句外面先将退位清零,
  用被减数再减去退位,
  {注意:由于每一个数位不一定都得向前一位借位,所以这里退位得清零。例如,234-25,个位需借位,而十位不用}
  接着,再判断,当被减数某一位不够减时,则需加上前一位退位过来的数。
  {注意:由于这里采用优化方法,所以退一位,就等于后一位加上10000。)
  最后,再拿一个数组来存储两个减数的差。
  jw:=0;
  for i:=260 downto k1 do
  a:=a- {此处jw为下一位从I位的借位}
  jw:=0; {此处jw为I 位准备向上一位的借位}
  if a&b then
  jw:=1;
  a:=a+10000;
  c:=a-b;
  ▲打印结果:
  先找到差的第一个非零数,如果差的所有位数都为零,就直接输出零。
  如果不是,就输出符号位和差的第一位。
  剩下部分,打印补足零:
  因为优化后的高精度减法,是把每四个数位分成一段,而每一段则必须有四个
  数,当有一段不足四个数时,就得用"0"补足.(如:第一位是'1',第二位是'34',第三位是'345',第四位是'8',
则应写为'8').注意:第一位不用补零,(如:第一位为'3',则写成'3').
  while (c[k]=0) and (k&=260) do k:=k+1;
  if k&260 then write('0')
  else begin
  write(fh,c[k]);{k是差的第1位;}
  for i:=k+1 to 260 do
  if c&1000 then write('0');
  if c&100 then write('0');
  if c&10 then write('0');
  write(c);
  参考程序:
  program Z
  const n=25;
  var s1,s2,s3,s4,s:
  a,b,c:array[1..n]
  i,k1,k2,l,code,jw:
  readln(s1);
  readln(s2);
  k1:=length(s1);
  k2:=length(s2);
  if k1&k2 then for i:=1 to k1-k2 do
s2:='0'+s2
  else for i:=1 to k2-k1 do s1:='0'+s1;
  cq:=' ';
  if s1&s2 then begin cq:='-'; s:=s1; s1:=s2; s2:=s;
  l:=length(s1);
  k1:=n;
  repeat
  s3:=copy(s1,l-3,4);
  val(s3,a[k1],code);
  k1:=k1-1;
  delete(s1,l-3,4);
  l:=l-4;
  until l&=0;
  k1:=k1+1;
  i:=length(s2);
  k2:=n;
  repeat
  s4:=copy(s2,i-3,4);
  val(s4,b[k2],code);
  k2:=k2-1;
  delete(s2,i-3,4);
  i:=i-4;
  until i&=0;
  k2:=k2+1;
  jw:=0;
  for i:=n downto k1 do
  jw:=0;
  if a&b then begin
  jw:=1;
  a:=a+10000;
  c:=a-b;
  while (c[k1]=0) and (k1&=n) do
  k1:=k1+1;
  if k1&n then writeln('0')
  else begin
  write(cq,c[k1]);
  for i:=k1+1 to n do
  if c&1000 then write('0');
  if c&100 then write('0');
  if c&10 then write('0');
  write(c);
高精度乘法
  高精度乘法基本思想和加法一样。其基本流程如下:
  ①读入被乘数s1,乘数s2
  ②把s1、s2分成4位一段,转成数值存在数组a,b中;记下a,b的长度k1,k2;
  ③i赋为b中的最低位;
  ④从b中取出第i位与a相乘,累加到另一数组c中;(注意:累加时错开的位数应是多少位?)
  ⑤i:=i-1;检测i值:小于k2则转⑥,否则转④
  ⑥打印结果
  参考程序:
  const n=100;
  type ar=array [1..n]
  var a,b: k1,k2,k:
  c:array [1..200]
  s1,s2:
  procedure fenge(s:var d: var kk:integer);
{将s分割成四位一组存放在d中,返回的kk值指向d的最高位}
  var ss:
  i,code:
  i:=length(s);
  kk:=n;
  repeat
  ss:=copy(s,i-3,4);
  val(ss,d[kk],code);
  kk:=kk-1;
  s:=copy(s,1,i-4);
  i:=i-4;
  until i&0;
  kk:=kk+1;
  var i:
  for i:=1 to n do begin a:=0; b:=0;
  for i:=1 to 2*n do c:=0;
  write('input 2 numbers:');
  readln(s1);
  readln(s2);
  fenge(s1,a,k1);
  fenge(s2,b,k2);
  var i,j,m: x,y,z,jw:
  i:=n; k:=2*n;
  repeat
  x:=b; z:=0; m:=k; jw:=0;
  for j:=n downto k1 do
  y:=a[j];
  z:=c[m];
  x:=x*y+z+
  jw:=x div 10000;
  c[m]:=x mod 10000;
  m:=m-1;
  if jw&&0 then c[m]:=jw else
  i:=i-1;
  k:=k-1;
  until i&k2;
  var i:
  write(c[k]);
  for i:=k+1 to 2*n do
  if c&1000 then write('0');
  if c&100 then write('0');
  if c&10 then write('0');
  write(c);
  教材“基础编”P87高精乘法参考程序:
  program ex3_1;
  a,b,c:array[0..1000]
  ok,i,j:
  readln(s);
  a[0]:=length(s);
  for i:=1 to a[0] do
  val(s[a[0]-i+1],a,ok);
  readln(s);
  b[0]:=length(s);
  b[0]:=length(s);
  for i:=1 to b[0] do
  val(s[b[0]-i+1],b,ok);
  var i,j,k:
  c[0]:=a[0]+b[0];
  for i:=1 to b[0] do
  for j:=1 to a[0]+1 do
  inc(c[i+j-1],a[j]*b mod 10);
  c[i+j]:=c[i+j]+(a[j]*b div 10)+(c[i+j-1] div 10);
  c[i+j-1]:=c[i+j-1] mod 10;
  var i:
  while c[c[0]]=0 do dec(c[0]);
  for i:=c[0] downto 1 do
  write(c);
高精度除法:
  1).高精度除以整型数据(integer);
  程序如下:
  program HighPrecision3_Multiply1;
  fn_inp='hp5.inp';
  fn_out='hp5.out';
  maxlen=100; { max length of the number }
  hp=record
  len: { length of the number }
  s:array[1..maxlen] of integer
  { s[1] is the lowest position
  s[len] is the highest position }
  procedure PrintHP(const p:hp);
  var i:
  for i:=p.len downto 1 do write(p.s);
  assign(input,fn_inp);
  reset(input);
  readln(st);
  x.len:=length(st);
  for i:=1 to x.len do { change string to HP }
  x.s:=ord(st[x.len+1-i])-ord('0');
  readln(z);
  close(input);
  procedure Divide(a:b:var c:var d:integer);
  { c:= d:=a mod b }
  var i,len:
  fillchar(c,sizeof(c),0);
  len:=a.
  for i:=len downto 1 do { from high to low }
  d:=d*10+a.s;
  while(len&1) and (c.s[len]=0) do dec(len);
  c.len:=
  Divide(x,z,y,w);
  assign(output,fn_out);
  rewrite(output);
  PrintHP(y);
  writeln(w);
  close(output);
  2).高精度除以高精度
  程序如下:
  program HighPrecision4_Multiply2;
  fn_inp='hp6.inp';
  fn_out='hp6.out';
  maxlen=100; { max length of the number }
  hp=record
  len: { length of the number }
  s:array[1..maxlen] of integer
  { s[1] is the lowest position
  s[len] is the highest position }
  x:array[1..2]
  y,w: { x: y:output }
  procedure PrintHP(const p:hp);
  var i:
  for i:=p.len downto 1 do write(p.s);
  assign(input,fn_inp);
  reset(input);
  for j:=1 to 2 do
  readln(st);
  x[j].len:=length(st);
  for i:=1 to x[j].len do { change string to HP }
  x[j].s:=ord(st[x[j].len+1-i])-ord('0');
  close(input);
  procedure Subtract(a,b:var c:hp); { c:=a-b, suppose
  var i,len:
  fillchar(c,sizeof(c),0);
  if a.len&b.len then len:=a.len { get the bigger
length of a,b }
  else len:=b.
  for i:=1 to len do { subtract from low to high }
  inc(c.s,a.s-b.s);
  if c.s&0 then
  inc(c.s,10);
  dec(c.s[i+1]); { add 1 to a higher position }
  while(len&1) and (c.s[len]=0) do dec(len);
  c.len:=
  function Compare(const a,b:hp):
  1 if a&b
  0 if a=b
  -1 if a & b
  var len:
  if a.len&b.len then len:=a.len { get the bigger
length of a,b }
  else len:=b.
  while(len&0) and (a.s[len]=b.s[len]) do
  { find a position which have a different digit }
  if len=0 then compare:=0 { no difference }
  else compare:=a.s[len]-b.s[len];
  procedure Multiply10(var a:hp); { a:=a*10 }
  var i:I
  for i:=a.len downto 1 do
  a.s[i+1]:=a.s;
  a.s[1]:=0;
  inc(a.len);
  while(a.len&1) and (a.s[a.len]=0) do
dec(a.len);
  procedure Divide(a,b:var c,d:hp); { c:= d:=a mod b
  var i,j,len:
  fillchar(c,sizeof(c),0);
  len:=a.
  fillchar(d,sizeof(d),0);
  d.len:=1;
  for i:=len downto 1 do
  Multiply10(d);
  d.s[1]:=a.s; { d:=d*10+a.s }
  { c.s:= d:= }
  { while(d&=b) do begin d:=d-b;inc(c.s) end }
  while(compare(d,b)&=0) do
  Subtract(d,b,d);
  inc(c.s);
  while(len&1)and(c.s[len]=0) do dec(len);
  c.len:=
  Divide(x[1],x[2],y,w);
  assign(output,fn_out);
  rewrite(output);
  PrintHP(y);
  PrintHP(w);
  close(output);
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 java高精度运算 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信