程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> “無限”位四則運算

“無限”位四則運算

編輯:Delphi

  由於標准的數字變量類型取值有限,如果需要進行運算的數字超過了范圍,用標准的數字變量類型就顯得無能為力了!下面的四個函數利用Delphi中的字符串對象實現了大數運算。

  加法、乘法由zswang編寫

  function StrLeft(const mStr: string; mDelimiter: string): string;
  begin
    Result := Copy(mStr, 1, Pos(mDelimiter, mStr) - 1);
  end; { StrLeft }

  function StrRight(const mStr: string; mDelimiter: string): string;
  begin
    if Pos(mDelimiter, mStr) <= 0 then
      Result := ''
    else Result := Copy(mStr, Pos(mDelimiter, mStr) + Length(mDelimiter), MaxInt);
  end; { StrRight }

  function formatnum(mNumber: string):string;
  var
    m:integer;
    TemStr:string;
  begin
    Result:='';
    for m:=1 to Length(mNumber) do
    begin
      if mNumber[m]='.' then
        Result:=Result+'.'
      else
        Result:=Result+IntToStr(StrToIntDef(mNumber[m], 0));
    end;
    while Pos('0', Result) = 1 do Delete(Result, 1, 1); //排除整數前無效的0
    if Pos('.', Result )<= 0 then Result := Result + '.'; //沒有有小數點補小數點
    TemStr:=StrRight(Result,'.');
    while Copy(TemStr, Length(TemStr), 1) = '0' do Delete(TemStr, Length(TemStr), 1); //排除小數後無效的0
    Result:=StrLeft(Result,'.')+'.'+TemStr;
    if Copy(Result, Length(Result), 1) = '.' then Delete(Result, Length(Result), 1); //排除無效小數點
    if Copy(Result, 1, 1)='.' then Result:='0'+Result;
    if (Result = '') then Result := '0';
  end;

  function InfiniteAdd(mNumberA, mNumberB: string): string; { 無限位數加法 }
  var
    I: Integer;
    T: Integer;
  begin
    Result := '';
    if Pos('.', mNumberA) <= 0 then mNumberA := mNumberA + '.'; //沒有有小數點補小數點
    if Pos('.', mNumberB) <= 0 then mNumberB := mNumberB + '.'; //沒有有小數點補小數點
    I := Max(Length(StrLeft(mNumberA, '.')), Length(StrLeft(mNumberB, '.'))); //整數部分最大長度
    mNumberA := DupeString('0', I - Length(StrLeft(mNumberA, '.'))) + mNumberA; //整數前補0
    mNumberB := DupeString('0', I - Length(StrLeft(mNumberB, '.'))) + mNumberB; //整數前補0
    T := Max(Length(StrRight(mNumberA, '.')), Length(StrRight(mNumberB, '.'))); //小數部分最大長度
    mNumberA := mNumberA + DupeString('0', T - Length(StrRight(mNumberA, '.'))); //小數後補0
    mNumberB := mNumberB + DupeString('0', T - Length(StrRight(mNumberB, '.'))); //小數後補0
    I := I + T + 1; //計算總長度//小數長度和整數長度加上小數點長度
    T := 0; //進位數初始化
    for I := I downto 1 do //從後向前掃描
      if [mNumberA[I], mNumberB[I]] <> ['.'] then begin //不是小數點時
        T := StrToIntDef(mNumberA[I], 0) + T; //累加當前數位
        T := StrToIntDef(mNumberB[I], 0) + T; //累加當前數位
        Result := IntToStr(T mod 10) + Result; //計算當前數位上的數字
        T := T div 10; //計算進位數
      end else Result := '.' + Result; //加上小數點
    if T <> 0 then Result := IntToStr(T mod 10) + Result; //處理進位數
    while Pos('0', Result) = 1 do Delete(Result, 1, 1); //排除整數前無效的0
    while Copy(Result, Length(Result), 1) = '0' do
      Delete(Result, Length(Result), 1); //排除小數後無效的0
    if Copy(Result, Length(Result), 1) = '.' then
      Delete(Result, Length(Result), 1); //排除無效小數點
    if Copy(Result, 1, 1) = '.' then Result := '0' + Result; //處理無0小數情況
    if (Result = '') then Result := '0'; //處理空字符情況
  end; { InfiniteAdd }

  function InfiniteMult(mNumberA, mNumberB: string): string; { 無限位數乘法 }

    function fMult(mNumber: string; mByte: Byte): string; { 無限位數乘法子函數 }
    var
      I: Integer;
      T: Integer;
    begin
      Result := '';
      T := 0;
      for I := Length(mNumber) downto 1 do begin //從後向前掃描
        T := StrToIntDef(mNumber[I], 0) * mByte + T; //累加當前數位
        Result := IntToStr(T mod 10) + Result; //計算當前數位上的數字
        T := T div 10; //計算進位數
      end;
      if T <> 0 then Result := IntToStr(T mod 10) + Result; //處理進位數
    end; { fMult }

  var
    I: Integer;
    vDecimal: Integer; //小數位數
    T: string;
  begin
    Result := '';
    ///////Begin 處理小數
    if Pos('.', mNumberA) <= 0 then mNumberA := mNumberA + '.'; //沒有有小數點補小數點
    if Pos('.', mNumberB) <= 0 then mNumberB := mNumberB + '.'; //沒有有小數點補小數點
    vDecimal := Length(StrRight(mNumberA, '.')) + Length(StrRight(mNumberB, '.')); //計算小數位數
    mNumberA := StrLeft(mNumberA, '.') + StrRight(mNumberA, '.'); //刪除小數點
    mNumberB := StrLeft(mNumberB, '.') + StrRight(mNumberB, '.'); //刪除小數點
    ///////End 處理小數
    T := '';
    for I := Length(mNumberB) downto 1 do begin
      Result := InfiniteAdd(Result, fMult(mNumberA, StrToIntDef(mNumberB[I], 0)) + T);
      T := T + '0';
    end;
    Insert('.', Result, Length(Result) - vDecimal + 1);
    while Pos('0', Result) = 1 do Delete(Result, 1, 1); //排除整數前無效的0
    while Copy(Result, Length(Result), 1) = '0' do
      Delete(Result, Length(Result), 1); //排除小數後無效的0
    if Copy(Result, Length(Result), 1) = '.' then
      Delete(Result, Length(Result), 1); //排除無效小數點
    if Copy(Result, 1, 1) = '.' then Result := '0' + Result; //處理無0小數情況
    if (Result = '') then Result := '0'; //處理空字符情況
  end; { InfiniteMult }

  function InfiniteSub(mNumberA, mNumberB: string): string; { 無限位數減法 }
  var
    I: Integer;
    T: Integer;
    TemNumA:String;
    minus:Boolean;
  begin
    Result := '';
    mNumberA:=formatnum(mNumberA);
    mNumberB:=formatnum(mNumberB);
    if Pos('.', mNumberA) <= 0 then mNumberA := mNumberA + '.'; //沒有有小數點補小數點
    if Pos('.', mNumberB) <= 0 then mNumberB := mNumberB + '.'; //沒有有小數點補小數點
    I := Max(Length(StrLeft(mNumberA, '.')), Length(StrLeft(mNumberB, '.'))); //整數部分最大長度
    mNumberA := DupeString('0', I - Length(StrLeft(mNumberA, '.'))) + mNumberA; //整數前補0
    mNumberB := DupeString('0', I - Length(StrLeft(mNumberB, '.'))) + mNumberB; //整數前補0
    T := Max(Length(StrRight(mNumberA, '.')), Length(StrRight(mNumberB, '.'))); //小數部分最大長度
    if ((Length(StrLeft(mNumberA, '.'))) > (Length(StrLeft(mNumberB, '.')))) or(((Length(StrLeft(mNumberA, '.'))) = (Length(StrLeft(mNumberB, '.'))))and(mNumberB>mNumberA))then
    begin
      TemNumA := mNumberA;
      mNumberA := mNumberB + DupeString('0', T - Length(StrRight(mNumberB, '.'))); //小數後補0
      mNumberB := TemNumA + DupeString('0', T - Length(StrRight(TemNumA, '.'))); //小數後補0
      minus:=True;
    end
    else
    begin
      mNumberA := mNumberA + DupeString('0', T - Length(StrRight(mNumberA, '.'))); //小數後補0
      mNumberB := mNumberB + DupeString('0', T - Length(StrRight(mNumberB, '.'))); //小數後補0
      minus:=False;
    end;
    I := I + T + 1; //計算總長度//小數長度和整數長度加上小數點長度
    T := 0; //進位數初始化
    for I := I downto 1 do //從後向前掃描
      if [mNumberA[I], mNumberB[I]] <> ['.'] then begin //不是小數點時
        T := StrToIntDef(mNumberB[I], 0) - T; //累加當前數位
        T := StrToIntDef(mNumberA[I], 0) - T; //累加當前數位
        if (T<0) and (I<>1) then
        begin
          T:=T+10;
          Result := IntToStr(T mod 10) + Result; //計算當前數位上的數字
          T := -1; //計算進位數
        end
        else
        begin
          Result := IntToStr(T mod 10) + Result; //計算當前數位上的數字
          T := T div 10; //計算進位數
        end;
      end else Result := '.' + Result; //加上小數點
    if T <> 0 then Result := IntToStr(T mod 10) + Result; //處理進位數
    while Pos('0', Result) = 1 do Delete(Result, 1, 1); //排除整數前無效的0
    while Copy(Result, Length(Result), 1) = '0' do
      Delete(Result, Length(Result), 1); //排除小數後無效的0
    if Copy(Result, Length(Result), 1) = '.' then
      Delete(Result, Length(Result), 1); //排除無效小數點
    if Copy(Result, 1, 1) = '.' then Result := '0' + Result; //處理無0小數情況
    if (Result = '') then Result := '0'; //處理空字符情況
    if minus then Result:='-'+Result;
  end; { InfiniteSub}

  function InfiniteDiv(mNumberA, mNumberB: string;n:integer): string; { 無限位數除法 }
  //n為有效數字個數

   function vDecimal(mNumber: string):integer;
   var m,x:integer;
   begin
     x:=0;
     if Pos('.', mNumber) <= 0 then
     begin
       for m:=Length(mNumber) downto 1 do
       begin
         if mNumber[m]='0' then x:=x+1 else Break;
       end;
       Result:=-x;
     end
     else
       Result:=Length(StrRight(mNumber, '.'));
   end;

   function formatnum2(mNumber: string):string;
   begin
     Result:=mNumber;
     if Pos('.', Result )<= 0 then Result := Result + '.';
     Result:=StrLeft(Result,'.')+StrRight(Result,'.');
     while Pos('0', Result) = 1 do
       Delete(Result, 1, 1);//排除整數前無效的0
     while Copy(Result, Length(Result), 1) = '0' do
       Delete(Result, Length(Result), 1);//排除小數後無效的0
   end;

  var
    I,J,t,v,y,Len: Integer;
    TemSub,TemNum: string;
  begin
    Result := '';
    mNumberA:=formatnum(mNumberA);
    mNumberB:=formatnum(mNumberB);
    v:=vDecimal(mNumberA)-vDecimal(mNumberB);
    mNumberA:=formatnum2(mNumberA);
    mNumberB:=formatnum2(mNumberB);
    if mNumberB='' then
      Result:='Err'
    else if mNumberA='' then
      Result:='0'
    else
    begin
    I:=0;
    if Length(mNumberA)>Length(mNumberB) then
      Len:=Length(mNumberB)
    else
      Len:=Length(mNumberA);
    if Copy(mNumberA,1,Len)>=Copy(mNumberB,1,Len) then
      J:=Length(mNumberB)
    else
      J:=Length(mNumberB)+1;
    for y:=1 to J do
    begin
      if Length(mNumberA)>=y then
        TemSub:=TemSub+mNumberA[y]
      else
      begin
        TemSub:=TemSub+'0';
        v:=v+1;
      end;
    end;
    while I<=n-1 do
    begin
      if TemSub[1]>mNumberB[1] then
        t:=StrToInt(TemSub[1]) Div StrToInt(mNumberB[1])
      else
        t:=StrToInt(TemSub[1]+TemSub[2]) Div StrToInt(mNumberB[1]);
      TemNum:=InfiniteMult(mNumberB,IntToStr(t));
      while (Length(TemNum)>Length(TemSub)) or ((Length(TemNum)=Length(TemSub))and(TemNum>TemSub)) do
      begin
        t:=t-1;
        TemNum:=InfiniteMult(mNumberB,IntToStr(t));
      end;
      Result:=Result+IntToStr(t);
      I:=I+1;
      TemSub:=InfiniteSub(TemSub,TemNum);
      if (TemSub='0') and (Length(mNumberA)<J) then
      begin
        v:=v+1;
        Break;
      end;
      if TemSub='0' then TemSub:='';
      J:=J+1;
      if Length(mNumberA)>=J then
      begin
        TemSub:=TemSub+mNumberA[J];
      end
      else
      begin
        TemSub:=TemSub+'0';
        v:=v+1;
      end;
    end;
    if Length(mNumberA)>=J then
      v:=v-(Length(mNumberA)-J)-1
    else
      v:=v-1;
    while Copy(Result, Length(Result), 1) = '0' do
    begin
      v:=v-1;
      Delete(Result, Length(Result), 1);
    end;
    if v>Length(Result) then
      Result:='.'+DupeString('0',v-Length(Result)) + Result
    else if v>0 then
      Insert('.', Result, Length(Result) - v +1); //插入小數點
    if v<0 then Result:=Result+DupeString('0',0-v);
    if Copy(Result, 1, 1)='.' then Result:='0'+Result; //小數前面補0
    end;
  end; { InfiniteDiv}

  一時消遣娛樂之作~~~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved