掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
多倍長演算の除算 (ID:34235)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
http://oku.edu.mie-u.ac.jp/~okumura/algo/algo_pas.html (「コンピュータ・アルゴリズム事典」のソース CHAP04.pas) で公開されている多倍長演算の除算で、小数点以下を求めようとして以下のようにコーディングしたのですが、除数と被除数の差が小さいとき小数点以下が正しく計算できません。 たとえば (a)9999999999999999999999999999999999 被除数 899999999999999999999999999999999 除数(先頭が8) (b)99999 被除数 9999 除数 などはだいじょうぶですが (c)9999999999999999999999999999999999 被除数 999999999999999999999999999999999 除数(先頭が9) (d)99999 被除数 98999 除数 などはダメです。 ちなみに最小桁しか用いない場合 (e)9999 被除数 9998 除数 のように差が1でもOKです。 いろいろ試行錯誤しながらコードを弄っているのですが、なかなかうまくいきません。解決策をご教示いただけたら幸いです。 ------------------------------------------------------------------------- 【CHAP04.pasを変更した部分】 const BASE = 10000; // 10000 進法 BASE_ONE = BASE-1; // BASE-1 = 9999 BASE2 = BASE*BASE; // BASE*BASE = 100,000,000(1億) MAXLEN = 100000; // BASE 進法での最大桁数 type Digit = 0..BASE_ONE; // 各桁の数(0 から 9999) TSuperLong = record Len: 0..MAXLEN; Num:array [0..MAXLEN] of Digit; end; 例外処理で writeln を使用していたところは raise Exception.Create に替えました。 ------------------------------------------------------------------------- //数値文字列を多倍長整数に変換 function StrToSuperLong(const S: string; n: Integer): TSuperLong; var X :TSuperLong; dmy :string; L, i, k:Integer; begin L := Length(S); i := 1; repeat k := L-i*n+1; if k < 1 then dmy := Copy(S,1,n-1+k) else dmy := Copy(S,k,n); X.Len := i; X.Num[X.Len] := StrToInt(dmy); Inc(i); until k <= 1; Result := X; end; //多倍長整数を数値文字列に変換 function TForm1.SuperLongToStr(X: TSuperLong): string; var i :Integer; begin Result := IntToStr(X.Num[X.Len]); for i := X.Len-1 downto 1 do Result := Result+Format('%.4d',[ X.Num[i] ]); if X.Len = 0 then Result := '0'; end; //小数点以下を求める procedure TForm1.Button1Click(Sender: TObject); var W, Bunshi, Bunbo, R, R2: TSuperLong; i: Integer; begin if (Edit1.Text = '') or (Edit2.Text = '') then Exit; W.Num[0] := 0; R.Num[0] := 0; R2.Num[0] := 0; Bunshi := StrToSuperLong(Edit1.Text,4);//数値文字列を多倍長整数に Bunbo := StrToSuperLong(Edit2.Text,4); if (Bunbo.Num[1] = 0) and (Bunbo.Len = 1) then begin MessageDlg('0 では割れません。', mtInformation, [mbOK], 0); Exit; end; LongDiv(W, Bunshi, Bunbo, R); //W:商 R:余 if R.Num[1] = 0 then Edit3.Text := SuperLongToStr(W) //多倍長整数を数値文字列に else begin Edit3.Text := SuperLongToStr(W)+'.'; ShortMul(R2,R,10); //余を10倍 for i := 1 to 30 do //小数点以下30桁 begin LongDiv(W, R2, Bunbo,R); Edit3.Text := Edit3.Text+SuperLongToStr(W); if R.Num[1] = 0 then break; ShortMul(R2,R,10); end; end; end;
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.