Форум: "Потрепаться";
Текущий архив: 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.043 c