Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.11.07;
Скачать: [xml.tar.bz2];

Вниз

Калькулятор   Найти похожие ветки 

 
Огромное Кулясищще ©   (2004-07-24 17:44) [0]

GrayFace - сюды пиши. Я как бы тоже решил заняться, но ушёл пить.


 
Юрий Зотов ©   (2004-07-24 18:18) [1]

Ребята, поверьте - это бесполезно. Зря тратите время.

В первоначальной ветке
http://delphimaster.net/view/14-1089499317/
я уже дважды писал: "До тех пор, пока не будет привлечена теория, ВСЕГДА найдется такое выражение, которое такой калькулятор распознать и выполнить не сможет".

Поймите, наконец, что это не афоризм и сказано не для красного словца. Это так и есть. Такое выражение действительно найдется ВСЕГДА, его надо только хорошо поискать.

Более того, мне кажется, что проанализировав алгоритм любого написанного без теории строчного калькулятора, всегда можно будет составить выражение, которое этот алгоритм не способен вычислить уже в самом своем принципе. То есть, указать выражение, полностью опровергающее сам алгоритм.


 
Юрий Зотов ©   (2004-07-24 18:22) [2]

Дополнение к [1].

Естественно, говоря "выражение", я имею в виду синтаксически правильное выражение, при вычислении которого не возникает математических ошибок (переполнения, деления на ноль и пр.).


 
GrayFace ©   (2004-07-24 18:29) [3]

Посмотрим. Пока что половина ошибок (в том числе и выловленных мной) были не в алгоритме, а в деталях, по причине спешки. Сейчас я серьезно модифицировал свой калькулятор - увеличил и подшлейфовал. Так что можно смело добавлять 1-2 часа.

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, Math;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   Button1: TButton;
   Edit2: TEdit;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

type TOperator=function(v1,v2:extended):extended;
    TFunction=function(v:extended):extended;

    TFunc=record
      f:pointer;
      name:string;
    end;
    TConst=record
      v:Extended;
      name:string;
    end;
    TBracketFunc=record
      f:pointer;
      left:string;
      right:char;
    end;
    TOper=record
      f:pointer;
      name:string;
      prior:integer;
    end;

function Mul(v1,v2:extended):extended;
begin
 Result:=v1*v2;
end;
function Div1(v1,v2:extended):extended;
begin
 Result:=v1/v2;
end;
function Add(v1,v2:extended):extended;
begin
 Result:=v1+v2;
end;
function Dec(v1,v2:extended):extended;
begin
 Result:=v1-v2;
end;
function Stepen(v1,v2:extended):extended;
begin
 Result:=exp(ln(v1)*v2);
end;
function Sin1(v:extended):extended;
begin
 Result:=sin(v);
end;
function Cos1(v:extended):extended;
begin
 Result:=cos(v);
end;
function Tg(v:extended):extended;
begin
 Result:=tan(v);
end;
function Ctg(v:extended):extended;
begin
 Result:=CoTan(v);
end;
function aSin(v:extended):extended;
begin
 Result:=arcsin(v);
end;
function aCos(v:extended):extended;
begin
 Result:=arccos(v);
end;
function aTg(v:extended):extended;
begin
 Result:=arctan(v);
end;
function aCtg(v:extended):extended;
begin
 if v=0 then Result:=pi/2
 else Result:=arcTan(1/v);
end;
function Modul(v:extended):extended;
begin
 Result:=abs(v);
end;

const Opers:array[0..4] of TOper=((f:@Add; name:"+"; Prior:10),(f:@dec; name:"-"; prior:10),(f:@Mul; name:"*"; prior:20),(f:@Div1; name:"/"; prior:20),(f:@stepen; name:"^"; prior:30));
     OpMul:TOper=(f:@Mul; name:"*"; prior:20);
     Funcs:array[0..7] of TFunc=((f:@sin1; name:"sin"),(f:@cos1; name:"cos"),(f:@tg; name:"tg"),(f:@ctg; name:"ctg"),(f:@asin; name:"arcsin"),(f:@acos; name:"arccos"),(f:@atg; name:"arctg"),(f:@actg; name:"arcctg"));
     BracketFuncs:array[0..0] of TBracketFunc=((f:@Modul; left:"|"; right:"|"));
     Consts:array[0..0] of TConst=((v:pi; name:"pi"));

function IsDigit(c:char):byte;
begin
 if (c=".") or (c=DecimalSeparator) or (c="e") or (c="E") or ((ord(c)>=$30) and (ord(c)<=$39))
 then result:=1 else if (c="-") or (c="+") then Result:=2 else Result:=0;
end;

procedure DoString(From,Tom:PChar; var s:string);
var i:integer;
begin
 SetLength(s,integer(tom)-integer(from)+1);
 for i:=1 to length(s) do
 begin
   if from^="." then s[i]:=DecimalSeparator
   else s[i]:=from^;
   inc(from);
 end;
end;

function cmp(const s:string; p:PChar):boolean;
var s1:string; l:integer;
begin
 l:=length(s);
 SetLength(s1,l);
 CopyMemory(@s1[1],p,l);
 Result:=AnsiCompareText(s,s1)=0;
end;

function GetOper(var s:PChar; sep:Char; prior:integer; var done:byte; v1:extended):extended; forward;
{----------------------------------------------}


 
GrayFace ©   (2004-07-24 18:30) [4]



var s1:string; i:integer; Len:integer; from,tom:PChar;
   step:integer;

function GetValue(var s:PChar; sep:Char; prior:integer; var done:byte):extended;
var dn:byte; fu:pointer;
begin
 try
   while s^=" " do inc(s);
   if s^="(" then
   begin
     inc(s);
     dn:=0;
     Result:=GetValue(s,")",-MaxInt,dn);
     exit;
   end;
   if s^="-" then
   begin
     inc(s);
     dn:=0;
     Result:=-GetValue(s,sep,MaxInt,dn);
     if dn=2 then done:=2;
     exit;
   end;
   len:=0;
   for i:=low(BracketFuncs) to high(BracketFuncs) do
   begin
     if (length(BracketFuncs[i].left)>len) and cmp(BracketFuncs[i].left,s) then
     begin
       step:=ord(BracketFuncs[i].right);
       fu:=BracketFuncs[i].f;
       len:=length(BracketFuncs[i].left);
     end;
   end;
   if len<>0 then
   begin
     inc(s,len);
     dn:=0;
     Result:=TFunction(fu)(GetValue(s,chr(step),-MaxInt,dn));
     exit;
   end;
   for i:=low(Funcs) to high(Funcs) do
   begin
     if (length(Funcs[i].name)>len) and cmp(Funcs[i].name,s) then
     begin
       fu:=Funcs[i].f;
       len:=length(Funcs[i].name);
     end;
   end;
   for i:=low(Consts) to high(Consts) do
   begin
     if (length(Consts[i].name)>len) and cmp(Consts[i].name,s) then
     begin
       fu:=nil;
       Result:=Consts[i].v;
       len:=length(Consts[i].name);
     end;
   end;
   if len<>0 then
   begin
     inc(s,len);
     if fu<>nil then
     begin
       dn:=0;
       Result:=TFunction(fu)(GetValue(s,sep,MaxInt,dn));
     end;
     exit;
   end;
   from:=s;
   tom:=nil;
   step:=0;
   if s^="+" then inc(s);
   while true do
   begin
     if IsDigit(s^)=0 then break;
     if (s^="e") or (s^="E") then if step<1 then step:=1 else break;
     if (s^="-") then if step=1 then inc(step) else break;
     if (s^="+") then if step=1 then inc(step) else break;
     if IsDigit(s^)=1 then tom:=s;
     inc(s);
   end;
   if tom=nil then
   begin
     raise Exception.Create("Syntax error");
   end;
   s:=tom;
   inc(s);
   DoString(from,tom,s1);
   try
     Result:=StrToFloat(s1);
   except
     raise Exception.Create("Syntax error");
   end;
 finally
   if done<>2 then
   begin
     dn:=0;
     while dn=0 do
     begin
       Result:=GetOper(s,sep,prior,dn,Result);
     end;
     if dn=2 then done:=2 else done:=0;
   end;
 end;
end;

function GetOper(var s:PChar; sep:Char; prior:integer; var done:byte; v1:extended):extended;
var op:TOper;
begin
 while s^=" " do inc(s);
 len:=0;
 if (s^=sep) or (s^=#0) then
 begin
   if s^<>sep then raise Exception.Create("Syntax error: ""+sep+"" wasn""t found");
   if s^<>#0 then inc(s);
   done:=2;
   Result:=v1;
   exit;
 end;
 for i:=low(opers) to high(opers) do
 begin
   if (length(Opers[i].name)>len) and cmp(Opers[i].name,s) then
   begin
     op:=Opers[i];
     len:=length(Opers[i].name);
   end;
 end;
 if Len=0 then op:=OpMul;
 if op.prior>prior then
 begin
   inc(s,Len);
   Result:=TOperator(op.f)(v1,GetValue(s,sep,op.prior,done))
 end else
 begin
   Result:=v1;
   done:=1;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var b:byte; p:PChar; s:string; i:integer;
begin
 b:=0;
 s:=Edit1.text;
 p:=PChar(s);
 try
   Edit2.Text:=FloatToStr(GetValue(p,#0,-MaxInt,b));
   Edit1.SetFocus;
   Edit1.SelLength:=0;
   Edit1.SelStart:=length(s);
 except
   on E: Exception do
   begin
     if s="" then i:=0 else i:=integer(p)-integer(@s[1]);
     Edit2.Text:=E.Message+" at offset "+IntToStr(i);
     Edit1.SetFocus;
     Edit1.SelStart:=i;
     Edit1.SelLength:=0;
   end;
 end;
end;

end.


 
Юрий Зотов ©   (2004-07-24 19:36) [5]

> GrayFace [3, 4]

Выражение: arctg(sin(|-2|)/cos(2))
Результат: Syntax error: ")" wasn"t found at offset 23

:о)


 
Anatoly Podgoretsky ©   (2004-07-24 19:51) [6]

Смело добавляем 1-2 часа и так до бесконечности.
Автор давно доказал, то что было сказано в первоначальной ветке.


 
GrayFace ©   (2004-07-24 21:02) [7]

Отсутствие опровержения - не есть доказательство.


 
GrayFace ©   (2004-07-24 21:22) [8]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, Math;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   Button1: TButton;
   Edit2: TEdit;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

type TOperator=function(v1,v2:extended):extended;
    TFunction=function(v:extended):extended;

    TFunc=record
      f:pointer;
      name:string;
    end;
    TConst=record
      v:Extended;
      name:string;
    end;
    TBracketFunc=record
      f:pointer;
      left:string;
      right:char;
    end;
    TOper=record
      f:pointer;
      name:string;
      prior:integer;
    end;

function Mul(v1,v2:extended):extended;
begin
 Result:=v1*v2;
end;
function Div1(v1,v2:extended):extended;
begin
 Result:=v1/v2;
end;
function Add(v1,v2:extended):extended;
begin
 Result:=v1+v2;
end;
function Dec(v1,v2:extended):extended;
begin
 Result:=v1-v2;
end;
function Stepen(v1,v2:extended):extended;
begin
 Result:=exp(ln(v1)*v2);
end;
function Sin1(v:extended):extended;
begin
 Result:=sin(v);
end;
function Cos1(v:extended):extended;
begin
 Result:=cos(v);
end;
function Tg(v:extended):extended;
begin
 Result:=tan(v);
end;
function Ctg(v:extended):extended;
begin
 Result:=CoTan(v);
end;
function aSin(v:extended):extended;
begin
 Result:=arcsin(v);
end;
function aCos(v:extended):extended;
begin
 Result:=arccos(v);
end;
function aTg(v:extended):extended;
begin
 Result:=arctan(v);
end;
function aCtg(v:extended):extended;
begin
 if v=0 then Result:=pi/2
 else Result:=arcTan(1/v);
end;
function Modul(v:extended):extended;
begin
 Result:=abs(v);
end;

const Opers:array[0..4] of TOper=((f:@Add; name:"+"; Prior:10),(f:@dec; name:"-"; prior:10),(f:@Mul; name:"*"; prior:20),(f:@Div1; name:"/"; prior:20),(f:@stepen; name:"^"; prior:30));
     OpMul:TOper=(f:@Mul; name:"*"; prior:20);
     Funcs:array[0..7] of TFunc=((f:@sin1; name:"sin"),(f:@cos1; name:"cos"),(f:@tg; name:"tg"),(f:@ctg; name:"ctg"),(f:@asin; name:"arcsin"),(f:@acos; name:"arccos"),(f:@atg; name:"arctg"),(f:@actg; name:"arcctg"));
     BracketFuncs:array[0..0] of TBracketFunc=((f:@Modul; left:"|"; right:"|"));
     Consts:array[0..0] of TConst=((v:pi; name:"pi"));

function IsDigit(c:char):byte;
begin
 if (c=".") or (c=DecimalSeparator) or (c="e") or (c="E") or ((ord(c)>=$30) and (ord(c)<=$39))
 then result:=1 else if (c="-") or (c="+") then Result:=2 else Result:=0;
end;

procedure DoString(From,Tom:PChar; var s:string);
var i:integer;
begin
 SetLength(s,integer(tom)-integer(from)+1);
 for i:=1 to length(s) do
 begin
   if from^="." then s[i]:=DecimalSeparator
   else s[i]:=from^;
   inc(from);
 end;
end;

function cmp(const s:string; p:PChar):boolean;
var s1:string; l:integer;
begin
 l:=length(s);
 SetLength(s1,l);
 CopyMemory(@s1[1],p,l);
 Result:=AnsiCompareText(s,s1)=0;
end;

function GetOper(var s:PChar; sep:Char; prior:integer; var done:byte; v1:extended):extended; forward;
{----------------------------------------------}


 
GrayFace ©   (2004-07-24 21:23) [9]

var s1:string; i:integer; Len:integer; from,tom:PChar;
   step:integer;

function GetValue(var s:PChar; sep:Char; prior:integer; var done:byte):extended;
var dn:byte; fu:pointer;
begin
 try
   while s^=" " do inc(s);
   if s^="(" then
   begin
     inc(s);
     dn:=0;
     Result:=GetValue(s,")",-MaxInt,dn);
     exit;
   end;
   if s^="-" then
   begin
     inc(s);
     dn:=0;
     Result:=-GetValue(s,sep,MaxInt,dn);
     done:=dn;
     exit;
   end;
   len:=0;
   for i:=low(BracketFuncs) to high(BracketFuncs) do
   begin
     if (length(BracketFuncs[i].left)>len) and cmp(BracketFuncs[i].left,s) then
     begin
       step:=ord(BracketFuncs[i].right);
       fu:=BracketFuncs[i].f;
       len:=length(BracketFuncs[i].left);
     end;
   end;
   if len<>0 then
   begin
     inc(s,len);
     dn:=0;
     Result:=TFunction(fu)(GetValue(s,chr(step),-MaxInt,dn));
     done:=dn;
     exit;
   end;
   for i:=low(Funcs) to high(Funcs) do
   begin
     if (length(Funcs[i].name)>len) and cmp(Funcs[i].name,s) then
     begin
       fu:=Funcs[i].f;
       len:=length(Funcs[i].name);
     end;
   end;
   for i:=low(Consts) to high(Consts) do
   begin
     if (length(Consts[i].name)>len) and cmp(Consts[i].name,s) then
     begin
       fu:=nil;
       Result:=Consts[i].v;
       len:=length(Consts[i].name);
     end;
   end;
   if len<>0 then
   begin
     inc(s,len);
     if fu<>nil then
     begin
       dn:=0;
       Result:=TFunction(fu)(GetValue(s,sep,MaxInt,dn));
       done:=dn;
     end;
     exit;
   end;
   from:=s;
   tom:=nil;
   step:=0;
   if s^="+" then inc(s);
   while true do
   begin
     if IsDigit(s^)=0 then break;
     if (s^="e") or (s^="E") then if step<1 then step:=1 else break;
     if (s^="-") then if step=1 then inc(step) else break;
     if (s^="+") then if step=1 then inc(step) else break;
     if IsDigit(s^)=1 then tom:=s;
     inc(s);
   end;
   if tom=nil then
   begin
     raise Exception.Create("Syntax error");
   end;
   s:=tom;
   inc(s);
   DoString(from,tom,s1);
   try
     Result:=StrToFloat(s1);
   except
     raise Exception.Create("Syntax error");
   end;
 finally
   if done<>2 then
   begin
     dn:=0;
     while dn=0 do
     begin
       Result:=GetOper(s,sep,prior,dn,Result);
     end;
     if dn=2 then done:=2 else done:=0;
   end;
 end;
end;

function GetOper(var s:PChar; sep:Char; prior:integer; var done:byte; v1:extended):extended;
var op:TOper;
begin
 while s^=" " do inc(s);
 len:=0;
 if (s^=sep) or (s^=#0) then
 begin
   if s^<>sep then raise Exception.Create("Syntax error: ""+sep+"" wasn""t found");
   if s^<>#0 then inc(s);
   done:=2;
   Result:=v1;
   exit;
 end;
 for i:=low(opers) to high(opers) do
 begin
   if (length(Opers[i].name)>len) and cmp(Opers[i].name,s) then
   begin
     op:=Opers[i];
     len:=length(Opers[i].name);
   end;
 end;
 if Len=0 then op:=OpMul;
 if op.prior>prior then
 begin
   inc(s,Len);
   Result:=TOperator(op.f)(v1,GetValue(s,sep,op.prior,done))
 end else
 begin
   Result:=v1;
   done:=1;
 end;
end;

{function Operate(var s:PChar; sep:char):extended;
var done:boolean;
begin
 result:=GetValue(s,sep);
 while true do
 begin
   Result:=GetOper(s,sep,Result,done);
 end;
end;
}
procedure TForm1.Button1Click(Sender: TObject);
var b:byte; p:PChar; s:string; i:integer;
begin
 b:=0;
 s:=Edit1.text;
 p:=PChar(s);
 try
   Edit2.Text:=FloatToStr(GetValue(p,#0,-MaxInt,b));
   Edit1.SetFocus;
   Edit1.SelLength:=0;
   Edit1.SelStart:=length(s);
 except
   on E: Exception do
   begin
     if s="" then i:=0 else i:=integer(p)-integer(@s[1]);
     Edit2.Text:=E.Message+" at offset "+IntToStr(i);
     Edit1.SetFocus;
     Edit1.SelStart:=i;
     Edit1.SelLength:=0;
   end;
 end;
end;

end.


 
Огромное Кулясищще ©   (2004-07-24 23:27) [10]

2 Юрий Зотов © (24.07.04 18:18) [1]:

Больше всего я боюсь, что вы введёте 1+-5 и вылетит ошибка. Я, конечно, проверочку сделаю, но будте добры н аэтом не настаивать.


 
Marser ©   (2004-07-24 23:45) [11]

Разбираться в коде лень, но ЮЗ как всегда прав. Нужно озннакомиться с теорией конечных автоматов...


 
Юрий Зотов ©   (2004-07-25 00:09) [12]

> GrayFace [8, 9]

То же самое выражение: arctg(sin(|-2|)/cos(2))
Но уже с другим результатом: Syntax error at offset 22
Время обнаружения глюка: несколько секунд.

:о)

Как Вы тестируете программу - для меня просто загадка. Хотелось бы все же попросить Вас выкладывать более тщательно протестированный код, иначе просто несерьезно получается.

P.S.
"До тех пор, пока к написанию калькулятора не будет привлечена теория, ВСЕГДА найдется такое выражение, которое калькулятор распознать и выполнить НЕ сможет".
© Юрий Зотов.
:о)


 
Anatoly Podgoretsky ©   (2004-07-25 00:52) [13]

Боюсь за стек но все же [6]


 
Думкин ©   (2004-07-25 06:44) [14]

Мне кажется будет лучшим выкладывать не код, а ссылку на ЗИП-архив.
Иначе скоро ветка будет весить несколько метров, а конца и видно не будет.
И про Банелла было здраво сказано, вполне хватит. Но своем здорово было бы и еще немного в теории. Сваять что-то можно, но это как раз и выльется в огромную потерю времени и итог почти нулевой, тгогда как после тнории получаешьоружие для всей жизни навсегда(надолго) и с возможностью расширений.


 
Думкин ©   (2004-07-25 06:46) [15]

Извинясь за очепятки, что к клаве новой не привыкну. :-))


 
}|{yk ©   (2004-07-25 13:10) [16]

Слушай, ну есть же уже очень простой подход к решению данной задачи. Так как ты решаешь ее не решить. Задача разбивается на 2 части - составление обратной польской записи (отдельно) и вычисление по отдельно этому преобразованию. Каждая из этих задач не сложна, и вместе они полностью решат поставленную задачу. Ты пытаешься решить задачу примитивным способом.


 
Romkin ©   (2004-07-25 13:52) [17]

Да конечные автоматы тут не очень и нужны, можно без них.
Способов множество. Код я смотреть не буду, но на первый взгляд он слишком длинный :))


 
Юрий Зотов ©   (2004-07-25 14:38) [18]

> }|{yk ©   (25.07.04 13:10) [16]

Можно обойтись и без польской записи, это не единственный способ. Но парсить все равно надо грамотно, а не доморощенными способами.

Фишка в том, что человек хочет доказать, что эту задачу можно решить и без теории. На коленке, как бы. Вот и доказывает. Ну не верит он в то, что без теории у него просто жизни не хватит, чтобы написать нормально работающий строчный калькулятор с более-менее развитым входным языком. Разве что он сам изобретет ту же самую (или свою) теорию.


 
Anatoly Podgoretsky ©   (2004-07-25 17:15) [19]

Юрий Зотов ©   (25.07.04 14:38) [18]
На это расчитывать не приходится, разве что просто откуда ни будь скопирует готовый код


 
Огромное Кулясищще ©   (2004-07-25 17:53) [20]

2 Юрий Зотов:

А предъявите требования к выражению? Какие операции должны поддерживаться?


 
Alx2 ©   (2004-07-25 17:54) [21]

>Фишка в том, что человек хочет доказать, что эту задачу можно
>решить и без теории
Можно и без теории. В этом частном случае. Даже не имея понятия о формальных языках и о грамматиках. Будет у автора желание обобщить сделанное (имею в виду то, что когда-нибудь получится полноценный калькулятор) - будет некая теория. А будет желание посмотреть "как большие пацаны это делают" - будет чувство а-ля "эх, нифига себе!", будет Большая теория :)
PS
Сужу исключительно по себе :)


 
Romkin ©   (2004-07-25 18:00) [22]

Огромное Кулясищще ©   (25.07.04 17:53) [20] Ты же сам уже все написал. Четыре арифметических действия плюс набор функций одного аргумента.


 
Огромное Кулясищще ©   (2004-07-25 18:18) [23]

>Четыре арифметических действия плюс набор функций одного

Как же... +, -, /, * - это конечно. Однако ещё возведение в степень через ^ надо бы. Кроме того - синус, косинус, тангенс, а вот арксинусы и ко - это просто лень уже. Кроме того, Зотов употребил модуль ввиде |a|. Думается, надо бы либо запретить и говорить, чтобы юзало abs(x), либо самому менять.


 
Ihor Osov'yak ©   (2004-07-25 18:20) [24]

2 [21] Alx2 ©   (25.07.04 17:54)

> Можно и без теории. В этом частном случае

Нет, в этом частном случае нельзя. Возможно только два варианта:
1. Либо все же полдучить теор. подготовку.
2. Пойти по пути, упомянутом в последнеи предложении постинга [18]. Но и в таком случае теория будет впереди.

Задача эта, несмотря на свою простоту, не из того ряда, что решается методом "инженерного тыка".. Да и метод "инженерного тыка" все же предполагает некоторую теоритическую подготовку :-).


 
Огромное Кулясищще ©   (2004-07-25 18:27) [25]

2 Ihor Osov"yak © (25.07.04 18:20) [24]:

Вы н абумажке посчитать пример можете? Думаю да. Значит, и комп может.


 
Ertong ©   (2004-07-25 18:34) [26]

Может я чего не понимаю, но помойму это задачка из ряда школьных оллимпиад! Я всегда решал ее. Там не очень сложный рекурсивный алгоритм. Если кому интересно, то где-то через часик сюда кину простейшую реализацию.


 
Alx2 ©   (2004-07-25 18:41) [27]

>Ihor Osov"yak ©   (25.07.04 18:20) [24]
Почему так категорично?
А эта конкретная задача решается именно методом не "инженерного тыка", а переложением своего "know how" на язык программирования (у кого на сколько ясно он формализуется). Тьюринга оставим пока в покое.Я утверждаю, что в этом конкретном случае теория вторична. Как необходимая вещь она возникла когда наступила своего рода "запарка" с подобными задачами и стал необходим универсальный инструмент. Конечно, когда мы уже имеем такой инструмент - подобные задачи выглядят детскими. Но к жизни этот аппарат побудили далеко не единичные задачи.
Но, не зная сего аппарата, САМОСТОЯТЕЛЬНО заставить программу работать так, как читает формулы любой нормальный человек - задача не из легких. И дай бог, если она удается. И радость от успеха ничуть не омрачается тем, что "есть уже такая теория". "Такая теория" просто послужит подтверждением и учителем в дальнейшем.


 
Ihor Osov'yak ©   (2004-07-25 18:58) [28]

2 [25] Огромное Кулясищще ©   (25.07.04 18:27)

Меня правилам разбора выражений учили, то бишь парсингу,  обучали этому, как его, "на ум пошло", а задача узнавания, она как бы уже на подсознательном уровне делается. Да и есть в наличии такое свойство, как интеллект (надеюсь).

А вот ваш алгоритм почти все это тоже должен уметь делать. Причем делать правильно, и для всех случаев. И не обладая интеллектом. Что повышает требования к качеству реализации алгоритма. Так как исключает обучение и самоусовершенстовование.

Так вот, составить такой алгоритм без соотв. теоритической подготовки  автора невозможно. И не важно, будет ли эта теория почерпнута из учебника, либо придумана автором  "c нуля". Важно, что теория будет впереди.
Почему теория? Да потому, что эта задачка уже для своего корректного решения требует знаний, выходящих за пределы элементарной арифметики и логики. То есть теории.
 Я понимаю, что сказанное выше мною не есть строгое доказательство. Я не философ и не специалист по теории алгоритмов, чтобы приводить строгое доказательство. Мало того, я даже не знаю, есть ли строгое доказательство.
В даном случае меня устраивают "нестрогие" доказательства, такие, как жизненный опыт, практика. Кстати, элемент "практики" мы наблюдаем :-).
Еще. Похожую задачку я решал лет 12-14 назад. Программирование у меня тогда еще не было профессией, но пожалуй, уже немного больше, чем хобби, но это не настолько важно.  Помню, ходил дня два, все думал, с какой стороны приступить.. А потом в библиотеке книжечка в руки попала, даже не помню, какая, что-то там о компиляторах с интерпретаторами рассказывалось. Так вот, после прочтение нескольких страничек с введением в теорию синтаксического анализа (если честно, даже не читал до конца (может и зря), а только просмотрел формализацию задачи, и общие подходы к разбору выражений) - как вдруг наступило просветление и озарение. Если не изменяет память, в тот же день был готовый релиз..


 
Piter ©   (2004-07-25 19:48) [29]

а что такое польская запись?


 
Ertong ©   (2004-07-25 19:56) [30]


> а что такое польская запись?

На algolist.manual.ru есть описание, но я не видел задачи, для которой ее использование было необходимо.

Да, вот исходник, правда на паскале, строчного калькулятора. Только четыре основные операции и дужки.

var
 s:string;  {string with expression}
 p:longint; {cursor position}
function expr:real; forward;

{Возвращает число, что начинается в позиции курсора и прередвинает курсор за число}
function number:real;
var
 n,st:real;
 b:boolean;
begin
 st:=1;
 n:=0;
 b:=false;
 while s[p] in ["0".."9","."] do
   begin
     if s[p]="." then
       begin
         b:=true;
         st:=10;
       end
      else
       begin
         if b then n:=n+(1/st)*(ord(s[p])-ord("0"))
              else n:=n*10+(ord(s[p])-ord("0"));
         st:=st*10;
       end;
     inc(p);
   end;
 number:=n;
end;

function factor:real;
var
 res:real;
begin
 if s[p]="-" then
   begin
     inc(p);
     res:=-factor;
   end;
 if s[p]="+" then
   begin
     inc(p);
     res:=factor;
   end;

 if s[p]="(" then
   begin
     inc(p);
     res:=expr;
     inc(p);
   end;
 if s[p] in ["0".."9","."] then res:=number;
 factor:=res;
end;

function term:real;
var
 n:real;
begin
 n:=number;
 while s[p] in ["*","/"] do
   begin
     inc(p);
     if s[p-1]="*" then  n:=n*number else n:=n/number;
   end;
 term:=n;
end;

function expr:real;
var
 n:real;
begin
 n:=term;
 while (s[p] in ["+","-"]) do
   begin
     if s[p] in ["+","-"] then
       begin
         inc(p);
         if s[p-1]="+" then n:=n+term else n:=n-term;
       end;
   end;
 expr:=n;
end;

begin
 readln(s);
 p:=1;
 writeln(expr:0:9);
 readln;
end.


Добавление степеней, функций и проверки ошибок дело техники.


 
Ertong ©   (2004-07-25 19:58) [31]

и унарный минус :)


 
Огромное Кулясищще ©   (2004-07-26 00:40) [32]

Ну, сколько то продвинулся. Думаю, завтра или послезавтра завершить, смотря как со временем будет.


 
Думкин ©   (2004-07-26 06:36) [33]

> [20] Огромное Кулясищще ©   (25.07.04 17:53)
> А предъявите требования к выражению? Какие операции должны  поддерживаться?

Почему это появляется только сейчас? Вообще, какая задача решается?
А будет считаться: $1AF0 xor $46B8 ?
Что в итоге будет?


 
Рамиль ©   (2004-07-26 08:17) [34]

Да бесполезно это без теории. Помнится я этот калькулятор за вечер сделал, как дополнительную фичу к курсовой по сплайнам, вооружившись тетрадкой с лекциями по теории компиляторов. Вычислялиь все выражения и ошибки в них ловились на этапе разбора. А тут уже n-ый день пишете и конца не видно...

> что в этом конкретном случае теория вторична.

Первична. Иначе все равно изобретешь теорию, но почти стопроцентно она будет кривой. Вообщем я солидарен с
> [18] Юрий Зотов ©   (25.07.04 14:38)


 
Рамиль ©   (2004-07-26 08:53) [35]


> [30] Ertong ©   (25.07.04 19:56)

Это прикол? Ни приоритетов операций, ни скобок.


 
Igorek ©   (2004-07-26 09:02) [36]

как все запущено...


 
Anatoly Podgoretsky ©   (2004-07-26 09:14) [37]

Прошло много рах по 3,5 часа а калькулятора все нет!


 
calm ©   (2004-07-26 09:38) [38]

Но парсить все равно надо грамотно, а не доморощенными способами.
Помнится, на 2-м курсе у нас был предмет "Теория выч. процессов".
Писать надо было автоматы, трансляторы, интерпретаторы и т.д.
И курсовик был.

Получив тему курсовика на второй неделе семестра, сразу стал им заниматься. Надо было проверять на допустимость выражение на любой граматике класса не помню какого.
Через неделю сделал. Все работало реально! Граматики задавались через текстовый файл, совершенно произвольно, все проверялось корректно, я был очень доволен.

Но автоматами там и не пахло, потому что до них еще не дошли на лекциях :)

К концу семестра я осознал, какой бред я написал :))
Господа, не отказывайтесь от изучения теории!


 
GrayFace   (2004-07-26 10:26) [39]

>Как Вы тестируете программу - для меня просто загадка.
Сам тащусь. :) Я немного сократил ваш пример и тестировал на урезанном.

>Кроме того, Зотов употребил модуль ввиде |a|.
Потому что я такую фичу добавил. Если напишишь *,/,-,+ и какой-нибудь sin - этого будет достаточно.

>Больше всего я боюсь, что вы введёте 1+-5 и вылетит ошибка.
Это неверное выражение - ошибка должна вылетать. (хотя у меня не вылетит)

>Мне кажется будет лучшим выкладывать не код, а ссылку на ЗИП-архив.
Да, но много мароки.

>Вы н абумажке посчитать пример можете? Думаю да. Значит, и комп может.
Тоже на бумажке? :)


 
Григорьев Антон ©   (2004-07-26 10:33) [40]


> GrayFace   (26.07.04 10:26) [39]
> >Больше всего я боюсь, что вы введёте 1+-5 и вылетит ошибка.
> Это неверное выражение - ошибка должна вылетать. (хотя у
> меня не вылетит)


С какой это радости оно неверное?



Страницы: 1 2 3 4 5 6 7 8 9 
10 11 12 13 14 15 16 17 18 
19 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.11.07;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.61 MB
Время: 0.046 c
1-1098439854
calm
2004-10-22 14:10
2004.11.07
XMLDocument, проблема при чтении xml-файла.


3-1097040092
KIR
2004-10-06 09:21
2004.11.07
На каком порте висит Intrbase


1-1098446890
ALEKCEY
2004-10-22 16:08
2004.11.07
Чтение строки из фаила выдаёт страшную ошибку


1-1097385449
focor
2004-10-10 09:17
2004.11.07
mousewheel


14-1097998461
Elpis
2004-10-17 11:34
2004.11.07
Программист - это не тот, кто пишет программы, а тот





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский