16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"無量大数の掛け算"
この発言に対し以下のコメントが寄せられています
#01088 Dia さん RE:無量大数の掛け算
みなさん、こんXXは。 かとちんです。\(^0^)/
nifty:FDELPHI/MES/10/7092 で発言した 128ビット整数の調査の際に、電卓
では無理なために作成した、滅茶苦茶でかい数値でも扱える掛け算です。
無量大数も軽く超えます。技術的に難しいことは一切やってません。小学校の
頃に習った掛け算の求め方を、やっているだけです。(^^;
冗長で恥ずかしいんですが、いつか何かの役に立つかなぁと思い登録します。
しかし、求めたとんでもなく長〜い数値文字列を、数値変換できないし、
今後何に使えるんでしょ。(^^;
(**
無量大数まで扱える掛け算
概要:
CPUの積算命令ではなく、小学生で習う掛け算の基本的な求め方を
用いることで、どんなに大きい数値(文字列)の掛け算でも算出する。
小数も扱える。
制限事項
指数表現には対応していない
パラメータ:
NumA ... 掛けられる側の数値文字列
NumB ... 掛ける側の数値文字列
戻り値:
NumA と NumB を掛けた結果の整数文字列
**)
function BigNumMul(NumA, NumB: string): string;
var
I, J: Integer;
SOut: string; // 一時的な計算結果
S: string; // 作業用文字列
A: Integer; // ある桁の計算結果
Ahure: Integer; // 位あふれ数値
OneToNineX: array [1..9] of string; // 予めNumAに1〜9を掛けた結果
Column: Integer; // 桁
ColumnOver: Boolean; // 全ての桁の加算の終了フラグ
AnsList: TStrings; // 各桁の掛け算結果を記憶する
FlowPtA, FlowPtB: Integer; // 各入力数値の小数点以下桁数
FlowPt: Integer; // 小数点以下桁数
begin
Result := '';
// パラメータチェック
if (Length(NumA) < 1) or (Length(NumB) < 1) then Exit;
NumA := Trim(NumA);
NumB := Trim(NumB);
if not (NumA[1] in ['-','+']) then NumA := '+' + NumA;
if not (NumB[1] in ['-','+']) then NumB := '+' + NumB;
FlowPtA := 0;
Column := 2;
while Column <= Length(NumA) do
begin
if (NumA[Column] = '.') and (FlowPtA = 0) then
begin
FlowPtA := Length(NumA) - Column;
NumA := Copy(NumA, 1, Column-1) +
Copy(NumA, Column+1, Length(NumA));
end else begin
if not (NumA[Column] in ['0'..'9']) then Exit;
end;
Inc(Column);
end;
FlowPtB := 0;
Column := 2;
while Column <= Length(NumB) do
begin
if (NumB[Column] = '.') and (FlowPtB = 0) then
begin
FlowPtB := Length(NumB) - Column;
NumB := Copy(NumB, 1, Column-1) +
Copy(NumB, Column+1, Length(NumB));
end else begin
if not (NumB[Column] in ['0'..'9']) then Exit;
end;
Inc(Column);
end;
FlowPt := FlowPtA + FlowPtB;
// 予めNumAに1〜9を掛けた結果を格納する
for I := 1 to 9 do
begin
SOut := '';
Ahure := 0;
J := Length(NumA);
while NumA[J] in ['0'..'9'] do
begin
A := (Ord(NumA[J])-$30) * I + Ahure;
SOut := IntToStr(A mod 10) + SOut;
Ahure := A div 10;
Dec(J);
end;
if Ahure > 0 then
begin
SOut := IntToStr(Ahure) + SOut;
end;
OneToNineX[I] := SOut;
end;
AnsList := TStringList.Create;
try
// 掛ける側の各桁の数値文字による掛け算結果を、記憶しておく
Column := 0;
while NumB[Length(NumB)-Column] in ['0'..'9'] do
begin
I := Ord(NumB[Length(NumB)-Column])-$30;
if I > 0 then
begin
AnsList.Append(OneToNineX[I] + StringOfChar(' ', Column));
end;
Inc(Column);
end;
Column := 0;
Ahure := 0;
SOut := '';
repeat
ColumnOver := True;
A := 0;
for I := 0 to AnsList.Count-1 do
begin
S := AnsList[I];
if Length(S) > Column then
begin
ColumnOver := False;
if S[Length(S)-Column] <> ' ' then
A := A + (Ord(S[Length(S)-Column])-$30);
end;
end;
A := A + Ahure;
SOut := IntToStr(A mod 10) + SOut;
Ahure := A div 10;
Inc(Column);
until ColumnOver;
if Ahure > 0 then
begin
SOut := IntToStr(Ahure) + SOut;
end;
finally
AnsList.Free;
end;
// 小数点以下桁数を反映する
if FlowPt > 0 then
begin
// 小数点を付加する
if Length(SOut) <= FlowPt then
begin
SOut := '0.' + StringOfChar('0', FlowPt-Length(SOut)) + SOut;
end else begin
SOut := Copy(SOut, 1, Length(SOut)-FlowPt) + '.' +
Copy(SOut, Length(SOut)-FlowPt+1, Length(SOut));
end;
// 小数点以下の最も右端に存在するゼロを除外する
for Column := Length(SOut) downto 1 do
begin
if SOut[Column] <> '0' then Break;
SOut := Copy(SOut, 1, Column-1);
end;
// 小数がなくなったら点を除外する
if SOut[Length(SOut)] = '.' then Delete(SOut, Length(SOut), 1);
end;
// 掛けた結果の符号
if NumA[1] <> NumB[1] then SOut := '-' + SOut;
Result := SOut;
end;
▲● 2000/05/25 03:47 JDX06162(とんちんかんちんかとちん)
■ Inprise Delphi ... The Great Development Kit
uses D2Desktop, D3CSS, D4CSS, D5ENT;
Original document by かとちん 氏 ID:(JDX06162)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|