「疯狂的高精度」高精度大模板

高精度都应该很熟练了,原理什么的也就不用多说。

当你把高精度加减乘除都摞在一起,就会有很神奇的事情发生——大模板诞生:

Pascal代码:

program High_Precision;

var
  os1,os2,os,md:ansistring;
  ch:char;
  u,v,l:integer;

function High_Precision_Addition(s1,s2:ansistring):ansistring;    //高精度加法
  var
    a,b:array[1..1000000] of integer;
    la,lb,k:integer;
    i:integer;
    s:ansistring;
  begin
    High_Precision_Addition:='';
    la:=length(s1);
    lb:=length(s2);
    fillchar(a,sizeof(a),0);
    fillchar(b,sizeof(b),0);
    for i:=1 to la do a[i]:=ord(s1[la-i+1])-48;  
    for i:=1 to lb do b[i]:=ord(s2[lb-i+1])-48;
    if la>lb then k:=la else k:=lb;
    for i:=1 to k do
      begin
        a[i+1]:=a[i+1]+(a[i]+b[i]) div 10;
        a[i]:=(a[i]+b[i]) mod 10;
      end;
    if a[k+1]>0 then k:=k+1;
    for i:=k downto 1 do
      begin
        str(a[i],s);
        High_Precision_Addition:=High_Precision_Addition+s;
      end;
  end;

function High_Precision_Subtraction(s1,s2:ansistring):ansistring;//高精度减法
  var
    a,b:array[1..1000000] of integer;
    s,p:ansistring;
    la,lb,k:integer;
    i:integer;
    symbol:char; 
  begin
    High_Precision_Subtraction:='';
    fillchar(a,sizeof(a),0);
    fillchar(b,sizeof(b),0);
    if s1=s2 then begin writeln(0) ;halt; end;
    if (length(s1)<length(s2)) or ((length(s1)=length(s2)) and(s1<s2)) then
      begin
        symbol:='-';
        s:=s1; s1:=s2; s2:=s;
      end;
    la:=length(s1); lb:=length(s2);
    for i:=1 to la do a[i]:=ord(s1[la-i+1])-48;
    for i:=1 to lb do b[i]:=ord(s2[lb-i+1])-48;
    k:=la;
    for i:=1 to k do
      begin
        if a[i]<b[i] then
          begin
            a[i+1]:=a[i+1]-1;
            a[i]:=a[i]+10;
          end;
        a[i]:=a[i]-b[i];
      end;
    while a[k]=0 do k:=k-1;
    if symbol='-' then High_Precision_Subtraction:=symbol+High_Precision_Subtraction;
    for i:=k downto 1 do
      begin
        str(a[i],p);
        High_Precision_Subtraction:=High_Precision_Subtraction+p;
      end; 
  end;

function High_Precision_Multiplication(s1,s2:ansistring):ansistring;//高精度乘法
  var
    la,lb,lc,x,i,j:longint;
    a,b,c:array [1..1000000] of longint;
    s:ansistring;
  begin
    la:=length(s1);lb:=length(s2);
    for i:=1 to la do a[la-i+1]:=ord(s1[i])-48;
    for i:=1 to lb do b[lb-i+1]:=ord(s2[i])-48;
    for i:=1 to la do
      begin
        x:=0;
        for j:=1 to lb 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;
    lc:=i+j;
    while (c[lc]=0)and(lc>1) do lc:=lc-1;
    for i:=lc downto 1 do
      begin
        str(c[i],s);
        High_Precision_Multiplication:=High_Precision_Multiplication+s;
      end;
  end;
  
function High_Precision_Division(s1,s2:ansistring;temp:integer):ansistring;//高精度除法(temp:{‘0’:相除保留10位小数;‘1’:取模;‘2’:求商})
  type
    hp=record
         len:integer;
         s:array[1..1000000] of integer;
       end;
  var
    x:array[1..2] of hp;  
    y,w:hp;   
    s:ansistring;
  procedure out(const p:hp);
    var
      i:integer;
    begin
      for i:=p.len downto 1 do
        begin
          str(p.s[i],s);
          High_Precision_Division:=High_Precision_Division+s;
        end;
    end;

  procedure init;
    var
      j,i:integer;
    begin
      if temp=0 then s1:=s1+'0000000000';             //提前加长保留10位小数
      x[1].len:=length(s1);
      for i:=1 to x[1].len do  
        x[1].s[i]:=ord(s1[x[1].len+1-i])-48;
      x[2].len:=length(s2);
      for i:=1 to x[2].len do         
        x[2].s[i]:=ord(s2[x[2].len+1-i])-48;
    end;

  procedure subtract(a,b:hp;var c:hp); 
    var
      i,len:integer;
    begin
      fillchar(c,sizeof(c),0);
      if a.len>b.len then len:=a.len else len:=b.len;
      for i:=1 to len do
        begin
          inc(c.s[i],a.s[i]-b.s[i]);
          if c.s[i]<0 then
            begin
              inc(c.s[i],10);
              dec(c.s[i+1]);
            end;
        end;
      while (len>1) and (c.s[len]=0) do dec(len); 
      c.len:=len;
    end;

  function compare(const a,b:hp):integer; 
    var
      len:integer;
    begin
      if a.len>b.len then len:=a.len else len:=b.len;
      while (len>0) and (a.s[len]=b.s[len]) do dec(len);
      if len=0 then compare:=0
      else compare:=a.s[len]-b.s[len];
    end;

  procedure multiply10(var a:hp);     
    var
      i:integer;
    begin
      for i:=a.len downto 1 do a.s[i+1]:=a.s[i];
      a.s[1]:=0;                             
      inc(a.len);
      while (a.len>1) and (a.s[a.len]=0) do dec(a.len);
    end;

  procedure divide(a,b:hp;var c,d:hp);    
    var
      i,j,len:integer;
    begin
      fillchar(c,sizeof(c),0);             
      len:=a.len;
      fillchar(d,sizeof(d),0); 
      d.len:=1;
      for i:=len downto 1 do
        begin
          multiply10(d);            
          d.s[1]:=a.s[i]; 
          while (compare(d,b)>=0) do 
            begin
              subtract(d,b,d);
              inc(c.s[i]);              
            end;
        end;
      while (len>1) and (c.s[len]=0) do dec(len);
      c.len:=len;
    end;
  begin
    init;                           
    divide(x[1],x[2],y,w);   
    if temp=0 then 
      begin 
        out(y);
        insert('.',High_Precision_Division,length(High_Precision_Division)-9); //加上小数点
      end;  
    if temp=1 then out(w); 
    if temp=2 then out(y);     
  end;

function Quick_Power(s1,s2,modulus:ansistring):ansistring;  //高精度快速幂
  var
    t,y:ansistring;
    x,l:integer;
  begin
    t:='1'; y:=s1;
    while s2<>'0' do
      begin
        val(s2[length(s2)],x,l);
        if odd(x)=true then t:= High_Precision_Multiplication(High_Precision_Division(t,modulus,1) , High_Precision_Division(y,modulus,1)); //t:=(t mod modulus)*(y mod modulus)
        y:=High_Precision_Multiplication(High_Precision_Division(y,modulus,1) , High_Precision_Division(y,modulus,1));  //y:=(y mod modulus)^2;  这里如果模数很大,就先不再加大代码长度,在外面套一个取模了(按理应该加上的)
        s2:=High_Precision_Division(s2,'2',2); 
      end;
    exit(High_Precision_Division(t,modulus,1));
  end;

begin
  readln(os1);
  readln(ch);
  readln(os2);
  case ch of                                                 //在主过程里处理运算符问题及符号问题
    '+':begin   {加法}
           if (os1[1]='-')and(os2[1]='-') then 
             begin
               delete(os1,1,1);
               delete(os2,1,1);
               writeln(High_Precision_Addition(os1,os2));
               halt;
            end;
           if (os1[1]='-')and(os2[1]<>'-') then
             begin
                delete(os1,1,1);
                writeln('-',High_Precision_Subtraction(os2,os1));
                halt;
             end;
           if (os1[1]<>'-')and(os2[1]<>'-') then 
             begin
               writeln(High_Precision_Addition(os1,os2));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]='-') then
             begin
               delete(os2,1,1);
               writeln(High_Precision_Subtraction(os1,os2));
               halt;
             end;
         end;
    '-':begin  {减法}
           if (os1[1]='-')and(os2[1]='-') then
             begin
               delete(os1,1,1);
               delete(os2,1,1);
               writeln(High_Precision_Subtraction(os2,os1));
               halt;
            end;
           if (os1[1]='-')and(os2[1]<>'-') then
             begin
               delete(os1,1,1);
               writeln('-',High_Precision_Addition(os1,os2));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]<>'-') then 
             begin
               writeln(High_Precision_Subtraction(os1,os2));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]='-') then 
             begin
               delete(os2,1,1);
               writeln(High_Precision_Addition(os1,os2));
               halt;
             end;
         end;
    '*':begin  {乘法}
           if (os1[1]='-')and(os2[1]='-') then
             begin
               delete(os1,1,1);
               delete(os2,1,1);
               writeln(High_Precision_Multiplication(os1,os2));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]<>'-') then
             begin
               writeln(High_Precision_Multiplication(os1,os2));
               halt;
             end;
           if (os1[1]='-')and(os2[1]<>'-')then
             begin
               delete(os1,1,1);
               writeln('-',High_Precision_Multiplication(os1,os2));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]='-') then
             begin
               delete(os2,1,1);
               writeln('-',High_Precision_Multiplication(os1,os2));
               halt;
             end;
         end;
    '/':begin  {除法}
           if (os1[1]='-')and(os2[1]='-') then
             begin
               delete(os1,1,1);
               delete(os2,1,1);
               writeln(High_Precision_Division(os1,os2,0));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]<>'-') then 
             begin
               writeln(High_Precision_Division(os1,os2,0));
               halt;
             end;
           if (os1[1]<>'-')and(os2[1]='-') then 
             begin
               delete(os2,1,1);
               writeln('-',High_Precision_Division(os1,os2,0));
               halt;
             end;
           if (os1[1]='-')and(os2[1]<>'-') then
             begin
               delete(os1,1,1);
               writeln('-',High_Precision_Division(os1,os2,0));
               halt;
             end;
         end;
    '%':begin  {取模}
            if (os1[1]='-')and(os2[1]='-') then
              begin
                delete(os1,1,1);
                delete(os2,1,1);
                writeln('-',High_Precision_Division(os1,os2,1));
                halt;
              end;
            if (os1[1]='-')and(os2[1]<>'-') then
              begin
                delete(os1,1,1);
                writeln(High_Precision_Division(os1,os2,1));
                halt;
              end;
            if (os1[1]<>'-')and(os2[1]='-') then
              begin 
                delete(os2,1,1);
                writeln('-',High_Precision_Division(os1,os2,1));
                halt;
              end;
            if (os1[1]<>'-')and(os2[1]<>'-') then 
              begin
                writeln(High_Precision_Division(os1,os2,1));
                halt;
              end;
          end;
    '^':begin  {乘方}
            readln(md);              //由于乘方会炸,这里建议再读入一个模数
            val(os2[length(os2)],v,l);
            if (os1[1]='-')and(odd(v)=true) then
              begin
                delete(os1,1,1);
                if (os2[1]='-') then 
                  begin
                    delete(os2,1,1);
                    writeln('-',High_Precision_Division('1',Quick_Power(os1,os2,md),0));
                  end
                else
                  writeln('-',Quick_Power(os1,os2,md));
                halt;
              end;
            if (os1[1]<>'-')and(odd(v)=true) then
              begin
                if (os2[1]='-') then
                  begin
                    delete(os2,1,1);
                    writeln(High_Precision_Division('1',Quick_Power(os1,os2,md),0));
                  end
                else
                  writeln(Quick_Power(os1,os2,md));
                halt;
              end;
            if (os1[1]='-')and(odd(v)=false) then
              begin
                delete(os1,1,1);
                if (os2[1]='-') then
                  begin
                    delete(os2,1,1);
                    writeln(High_Precision_Division('1',Quick_Power(os1,os2,md),0));
                  end
                else
                  writeln(Quick_Power(os1,os2,md));
                halt;
              end;
            if (os1[1]<>'-')and(odd(v)=false) then
              begin
                if (os2[1]='-') then
                  begin
                    delete(os2,1,1);
                    writeln(High_Precision_Division('1',Quick_Power(os1,os2,md),0));
                  end
                else
                  writeln(Quick_Power(os1,os2,md));
                halt;
              end;
      end;
  end;
end.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值