Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.30;
Скачать: CL | DM;

Вниз

Разбор математического выражения   Найти похожие ветки 

 
Anton_112   (2006-05-14 01:05) [0]

Задача - пользователь вводит выражение, необходимо представить его в памяти в виде двоичного дерева.
Думаю, несложно будет сделать вызывая рекурсивно процедуру добавления узла для каждого действия. В корне дерева должно находиться действие, которое при вычислении будет выполнено последним. Возникла трудность, как найти в выражении это действие. В идеале - его позицию в строке.
например:
28+3*2-(7+14)*12/3+79
при разборе должно указать на последний плюс.
28+3*2-(7+14)*12/3+79


 
Германн ©   (2006-05-14 01:45) [1]

Ищи в гугле или яндексе "обратная польская запись" и да прибудет тебе успех.


 
Anton_112   (2006-05-14 02:08) [2]

Спасибо, думаю это мне поможет. Я и начал с google, но не знал как сформулировать запрос :)


 
Жуков Олег   (2006-05-14 03:40) [3]

Показалось интересным, написал - вычисление выражения с помощью двоичного дерева. Причесать, выловить глюки и можно сдавать:
type
 TOperandStyle = (osNumber, osExpression);

 TOperand = class
 private
   FStyle: TOperandStyle;
   FValue: Extended;
   FOperand1: TOperand;
   FOperand2: TOperand;
   FAction: Char;
 protected
   function GetValue(): Extended;
 public
   property Value: Extended read GetValue write FValue;

   constructor Create(Expression: string);
   destructor Destroy(); override;

 end;

{ TOperand }

function TOperand.Getvalue(): Extended;
begin
 if FStyle = osNumber then
   Result := FValue
 else
   case FAction of
     "+": Result := FOperand1.Value + FOperand2.Value;
     "-": Result := FOperand1.Value - FOperand2.Value;
     "*": Result := FOperand1.Value * FOperand2.Value;
     "/": Result := FOperand1.Value / FOperand2.Value;
   else
     raise Exception.Create("Unknown action.");
   end;
end;

constructor TOperand.Create(Expression: string);
var
 Index: Integer;
 BracketCount: Integer;
 OperandExpression1, OperandExpression2: string;
 PassNumber: Integer;
 Completed : Boolean;
begin
 inherited Create();
 FStyle := osNumber;
 Expression := Trim(Expression);
 if Expression[1] = "(" then
   if Pos(")", Expression) = Length(Expression) then
     Expression := Copy(Expression, 2, Length(Expression) - 2);

 Completed := False;
 PassNumber := 1;

 while (PassNumber <= 2) and not Completed do
 begin
   BracketCount := 0;
   OperandExpression1 := "";
   OperandExpression2 := "";
   Index := Length(Expression);
   while (Index > 0) and not Completed do
   begin

     case Expression[Index] of
       ")":
       begin
         Inc(BracketCount);
       end;

       "(":
       begin
         Dec(BracketCount);
       end;

       "+", "-", "*", "/":
       if (BracketCount = 0)
         and ((Expression[Index] in ["+", "-"]) or (PassNumber = 2)) then
       begin
         FStyle := osExpression;
         FOperand2 := TOperand.Create(OperandExpression2);
         OperandExpression1 := Copy(Expression, 1, Index - 1);
         FOperand1 := TOperand.Create(OperandExpression1);
         FAction := Expression[Index];
         Completed := True;
       end;

     end;

     OperandExpression2 := Expression[Index] + OperandExpression2;
     Dec(Index);

   end; // while Index < Length(s) do

   Inc(PassNumber);
 end;

 if FStyle = osNumber then
 begin
   FValue := StrToFloat(Expression);
 end;

end;

destructor TOperand.Destroy();
begin
 if Assigned(FOperand1) then
   FOperand1.Destroy();
 if Assigned(FOperand2) then
   FOperand2.Destroy();
 inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Operand: TOperand;
begin
 Operand := TOperand.Create(Edit1.Text);
 try
   Edit2.Text := FloatToStr(Operand.Value);
 finally
   Operand.Free();
 end;
end;


 
TUser ©   (2006-05-14 07:28) [4]

http://algolist.manual.ru/syntax/index.php


 
Anton_112   (2006-05-15 00:26) [5]

Спасибо, работа на день останавливалась ,но с помощью обратной польской записи задачу почти решил. К тому же спасибо за приведенное здесь решение.
Возник вопрос - можно смело полагать ,что действие, оказавшееся в обратной польской записи последним, и должно выполняться последним в выражении? Просто этот алгоритм раньше был мне неизвестен, и пока что я не смог до конца понять его.


 
Германн ©   (2006-05-15 01:15) [6]


> Возник вопрос - можно смело полагать
> ,что действие, оказавшееся
> в обратной польской записи последним, и должно выполняться
> последним в выражении? Просто этот алгоритм раньше был мне
> неизвестен, и пока что я не смог до конца понять его.


Этот алгоритм - "классика  жанра". Так что можно "смело полагаться на него", но вот на конкретную реализацию полагаться не следует. Её нужно тщательно проверять.


 
Anton_112   (2006-05-15 02:26) [7]

Увы, реализовал его с использованием стека ,и на одной из простых проверок он выдал неверный результат... Хотелось бы закончить самаому, но время поджимает, поэтому вопрос к Жукову Олегу, не могли бы вы словами хотя бы вкратце рассказть как разделяете строку с выражением на OperandExpression1 и OperandExpression2? Просмотрев исходник я боюсь что не до конца понял ваш подход.
P.S: Извините за настойчивость


 
Жуков Олег   (2006-05-15 02:56) [8]


> Anton_112   (15.05.06 02:26) [7]

Там всё просто - идём по строке от последнего символа к первому, как только встречаем знак "-" или "+" вне скобок (это соответсвует BracketCount = 0),  значит всё, что справа - Expression2, а всё что слева - Expression1 (кстати, можно оптимизировать код по скорости, если Expression2 выделять именно в этот момент, а не прибавлять посимвольно на каждом витке цикла). Тогда разбор строки завершается, запоминается действие, и дальнейший разбор поручается дочерним Operand1 и Operand2,. Если же в первом проходе не обнаружено знаков "+" или "-", запускается второй такой-же проход, в котором точно так же ищется уже знак "*" или "/" (PassNumber=2, здесь тоже можно ускорить, если запоминать позицию знака в дополнительную переменную в первом проходе, тогда можно обойтись одним проходом). Ну а дальше дочерние операнды сами разруливают переданные им выражения, и строят дерево вниз. Если в строке не обнаружено знаков "+", "-", "*", "/", то считается, что это просто число. Ещё там можно выкинуть Completed, его проверка заменяется на  FStyle = osExpression.


 
Anton_112   (2006-05-15 15:24) [9]

Спасибо, я сам придумал похожий алгоритм, но этот выглядит "элегантнее".
Благодарю.


 
StymPunk   (2006-05-31 23:54) [10]


> Anton_112


Здравствуйте,
Вы не могли бы скинуть мне свою програмку на мыло? :-)


 
Joker007   (2006-06-18 23:23) [11]

Если вы еще тут, не могли бы вы рассказать поподробнее о работе своей программки – что происходит с выражением после того, как пользователь вводит выражение.


 
Германн ©   (2006-06-19 02:16) [12]


> Joker007   (18.06.06 23:23) [11]
>
> Если вы еще тут, не могли бы вы рассказать поподробнее о
> работе своей программки – что происходит с выражением после
> того, как пользователь вводит выражение.


А рассказать нужно "с выражением"? :-)


 
Joker007   (2006-06-19 12:22) [13]

Было бы неплохо :-)))


 
TUser ©   (2006-06-19 12:49) [14]


> Возник вопрос - можно смело полагать ,что действие, оказавшееся
> в обратной польской записи последним, и должно выполняться
> последним в выражении?

Не должно, а может - одно и тоже выражение можно записать в виде разных обратных польских записей.


 
Германн ©   (2006-06-20 02:23) [15]


> Не должно, а может - одно и тоже выражение можно записать
> в виде разных обратных польских записей.


Объясни, пожалуйста. Что, как и почему?


 
TUser ©   (2006-06-20 03:30) [16]

1+2+3 может быть записано как 1 2 + 3 + или как 2 3 + 1 +. Соотвественно, какой плюс выполнится последним - зависит от алгоритма разбора.


 
atruhin ©   (2006-06-20 05:55) [17]

> Соотвественно, какой плюс выполнится последним - зависит
> от алгоритма разбора.

Это преобразование выражения. Алгоритм разбора должен выдавать оригинальный порядок.



Страницы: 1 вся ветка

Текущий архив: 2006.07.30;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.036 c
2-1152678274
Rubey
2006-07-12 08:24
2006.07.30
Нестандартный размер формы


2-1152413062
KLAUS
2006-07-09 06:44
2006.07.30
Работа с ресурсами


2-1152273788
Santik
2006-07-07 16:03
2006.07.30
Цикл по времени


15-1151488549
ANB
2006-06-28 13:55
2006.07.30
США ущемляют атеистов


15-1151425083
Джо
2006-06-27 20:18
2006.07.30
Этот сайт в "облегченной" версии для моб. устройств