|
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"逆ポーランド変換、計算"
「中置記法」の計算式を「逆ポーランド記法」に変換し、計算するルーチンを
作ってみました。
unit ReversePolish;
interface
uses
SysUtils, Classes;
procedure Infix2RP(StIn, StOut: TStringList);
function CalcRPN(St: TStringList): Currency;
implementation
//----------------------------------------------------------------------------
function Priority(S: String): Integer;
begin
S := Trim(S);
if S = '=' then
Result := 0
else if S = ')' then
Result := 1
else if S = '+' then
Result := 2
else if S = '-' then
Result := 2
else if S = '*' then
Result := 3
else if S = '/' then
Result := 3
else if S = '(' then
Result := 4
else
Result := 5;
end;
//----------------------------------------------------------------------------
// 変換処理
// StIn : 中置記法 A = ( B - C ) / D + E * F
// StOut: 逆ポーランド記法 A B C - D / E F * + =
//----------------------------------------------------------------------------
procedure Infix2RP(StIn, StOut: TStringList);
var
StStack: TStringList;
i: Integer;
Token: String;
begin
StStack := TStringList.Create;
try
for i := 0 to StIn.Count - 1 do
begin
Token := Trim(StIn[i]);
if Length(Token) = 0 then
Continue;
while (StStack.Count <> 0) and
(StStack[StStack.Count - 1] <> '(') and
(Priority(Token) <= Priority(StStack[StStack.Count - 1])) do
begin
if (StStack[StStack.Count - 1] <> '(') and (StStack[StStack.Count - 1]
<> ')') then
StOut.Add(StStack[StStack.Count - 1]);
StStack.Delete(StStack.Count - 1);
end;
if Token <> ')' then
begin
StStack.Add(Token);
end
else
begin
StStack.Delete(StStack.Count - 1);
end;
end;
while (StStack.Count <> 0) do
begin
if (StStack[StStack.Count - 1] <> '(') and (StStack[StStack.Count - 1]
<> ')') then
StOut.Add(StStack[StStack.Count - 1]);
StStack.Delete(StStack.Count - 1);
end;
finally
StStack.Free;
end;
end;
//----------------------------------------------------------------------------
// 逆ポーランド記法の計算式を計算
//----------------------------------------------------------------------------
function CalcRPN(St: TStringList): Currency;
var
StStack: TStringList;
i: Integer;
wkC, op1, op2: Currency;
begin
StStack := TStringList.Create;
try
for i := 0 to St.Count - 1 do
begin
try
wkC := StrToFloat(St[i]);
StStack.Add(St[i]);
except
begin
op2 := StrToFloat(StStack[StStack.Count - 1]);
StStack.Delete(StStack.Count - 1);
op1 := StrToFloat(StStack[StStack.Count - 1]);
StStack.Delete(StStack.Count - 1);
if St[i] = '/' then
wkC := op1 / op2
else if St[i] = '*' then
wkC := op1 * op2
else if St[i] = '-' then
wkC := op1 - op2
else if St[i] = '+' then
wkC := op1 + op2;
StStack.Add(FloatToStr(wkC));
end;
end;
end;
Result := StrToFloat(StStack[StStack.Count - 1]);
finally
StStack.Free;
end;
end;
end.
使い方は、Form に TMemo を2つと、TButton を2つ、TEdit を配置し、
ReversePolish を uses します。
procedure TForm1.Button1Click(Sender: TObject);
begin
Infix2RP(TStringList(Memo1.Lines), TStringList(Memo2.Lines));
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Edit1.Text := FloatToStr(CalcRPN(TStringList(Memo2.Lines)));
end;
( 2 + 4 ) * ( 3 - 1 ) を計算する場合は、Memo1 に1行に1トークンずつ指
定します。例えば、
(
2
+
4
)
*
(
3
-
1
)
Button1 をクリックすると Memo2 に
2
4
+
3
1
-
*
と表示されます。更に Button2 をクリックすると Edit1 に
12
と、計算結果が表示されます。
島村 幸一
http://www.bekkoame.ne.jp/~joe90/
- FDELPHI MES(16):玉石混淆みんなで作るSample蔵【見本蓄積】 01/01/18 -
Original document by 島村 幸一 氏 ID:(MAF01541)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|