お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
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