Вверх ↑
Этот топик читают: Гость
Ответов: 8908
Рейтинг: 823
#76: 2014-06-27 20:18:53 ЛС | профиль | цитата
nesco, "Благородные Доны" уже жаловались, что смысл рассуждений других "Благородных Донов" ускользает, особенно в части классов, объектов, родителей и наследников...
карма: 19

0
Ответов: 9906
Рейтинг: 351
#77: 2014-06-27 21:58:22 ЛС | профиль | цитата
Давайте так, формула для MathParse, как ни крути - есть запись на некотором формальном языке.
Не виноватый я, что так оно и есть на самом деле

И, по большому счету, этот язык должен быть разжеван в справке на элемент.
Максимально лаконичная форма описания языка - это и есть синтаксическая диаграмма, которую я привел для нашего конкретного случая.
Как бы на языке РБНФ. Для которого тоже синтаксис точно так же можно описать на ем же.

Альтернатива - смотри код. Ну ей-ей, посмотреть на выше приведенные 7 формул - проще, чем лопатить 1000 строк кода.
Фишка в том, смысл этих 1000 строк - реализовать эти 7 формул.
У меня есть предложения для их изменения.
Как мне, спрашивается поступить: выложить новые формулы для обсуждения, или сказать - смотрите как славно я 1000 строк кода перелопатил ???

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

Ну и наконец, кто-то разве отказывался отвечать на вопросы, коль скоро таковые возникнут ???

карма: 9

0
Разработчик
Ответов: 26104
Рейтинг: 2124
#78: 2014-06-29 00:13:50 ЛС | профиль | цитата
Вот, я попробовал изменить CalcErrPos. Теперь строки будут считаться с 1 и будут отображаться первыми, те -- строка:позиция, как во всех редакторах сделано. Посмотрите. как там чего, все ли нормально, может подкорректируете, потом добавлю изменения на SVN, выкинув все ненужное.

himathparse.zip

Galkov, большая ли разница в применении не

  i := i + 2;
а

  inc(i, 2);
что бы ты рекомендовал испльзовать

Да, хотел еще спросить -- а не возникнит ли ситуация, когда вместо #13#10, переводом строки будет только #13, стоит ли это учесть
карма: 22

0
файлы: 1himathparse.zip [5.7KB] [362]
Разработчик
Ответов: 4698
Рейтинг: 426
#79: 2014-06-29 01:42:47 ЛС | профиль | цитата
В первом посте обновлен компонент и тестовая схема. Изменения:
- Декомпиляция байткода теперь происходит только при подключении точки onDebugText и работает всегда (т.е. не зависит от режима работы компонента).
- Код избавлен от применения классов, что дало прирост производительности чистых вычислений в 5 раз. (на старых тестах это не так заметно).
- Исправлены баги, упоминавшиеся выше.
карма: 10
1
Голосовали:sla8a
Ответов: 9906
Рейтинг: 351
#80: 2014-06-29 12:56:36 ЛС | профиль | цитата
nesco писал(а):
Да, хотел еще спросить -- а не возникнет ли ситуация, когда вместо #13#10, переводом строки будет только #13, стоит ли это учесть

Я думаю, что фигня все это...
А вот Кладов думает по-другому -- и учитывает это. Можно посмотреть в TStrList.SetText
Смотри сам, в общем

nesco писал(а):
большая ли разница в применении

Да никакой, как мне кажется. Компиляторы - тупы, конечно же. Но не до такой степени
Но я не поленился, и посмотрел дизасм для обоих вариантов - действительно, абсолютно пофиг
Вот он, для твоего фрагмента кода (комментарии мои):
.....
.00410CC9: 43 inc ebx // inc(nStr);
.00410CCA: BE01000000 mov esi,000000001 // nPos := 1;
.00410CCF: 83C102 add ecx,002 ;" " // i := i + 2; или inc(i,2); -- пофиг
.00410CD2: EB01 jmps .000410CD5 // Continue;
.00410CD4: 41 inc ecx // inc(i);
.00410CD5: 3B4DFC cmp ecx,[ebp][-04] // while (i < Value)...
.00410CD8: 7CDB jl .000410CB5
.....
Вот чего БЫ я делал - не использовал БЫ Continue.
По любому, один INC быстрее любого перехода (со сбросом конвейера)
#pas
.....
while i < Value do
begin
.....
inc(nStr);
nPos := 1;
inc(i);
end;
inc(i);
end;
.....
карма: 9

0
Разработчик
Ответов: 26104
Рейтинг: 2124
#81: 2014-06-29 15:09:44 ЛС | профиль | цитата
Galkov писал(а):
По любому, один INC быстрее любого перехода (со сбросом конвейера)

У меня изначально вообще было так

.....
while i < Value do
begin
.....
inc(nStr);
nPos := 0;
end;
inc(i);
end;
.....
Но мне показалось не правильным оставлять один пустой прогон. Так что, КМК, твой вариант более правильный.
------------ Дoбавленo в 15.09:
Galkov писал(а):
Смотри сам, в общем

С твоим предложением это оказалось реализовать довольно просто. Окончательные исправления на SVN.
карма: 22

0
Ответов: 9906
Рейтинг: 351
#82: 2014-06-30 10:58:14 ЛС | профиль | цитата
Это правда.
Ничем этот код не хуже: что раньше было два логических сравнения, что сейчас - те же два.


------------ Дoбавленo в 08.17:
Assasin, для сведения:
Дельфячья строка гарантирует нулик за своим "концом" (для совместимости со всякими другими системами, например WinApi).
Следовательно, ты зря напрягался за этот код:

#pas
i := length(FProgram);
SetLength(FProgram,i+length(str)+1);
Move(str[1], FProgram[i], length(str)+1);
-- это не ошибка, так просто короче
------------ Дoбавленo в 09.16:
Ыще
Чувствую недопонимание :
#pas
CmdDiv: {$ifdef F_P}if x2=0 then begin Err:=2;Exit;end else{$endif}
Fsp^ := Fsp^ / x2;
Под Дельфи эти супер проверки тупо НЕ НУЖНЫ (зачем ты их там оставил?). Спрашивается, зачем напрягать как компилятор, так и процессор.
Исключения - есть объективная данность камня, и тебя никто не спрашивал, нравятся они тебе, или нет.
Они все равно произойдут (ни о чем тебя не спрашивая).
Просто - посчитай чего нибудь типа 200^200. И ощути разницу между Дельфи и FPC.
Второй делал проверки, и все равно упал. А первый не делал - и все нормально (в смысле - сообщает об ошибке никуда не падая).
Ибо настоящая проверка делается в камне. И фиг ты сделаешь ее "самостоятельно".
В камне - чтобы пользователь мог заниматься делом, а не проверкой осуществимости своих делов.
Собственно, и наша то задача - Калькулятор, а не Проверятель Возможности Калькуляции.

А упасть можно и на умножении (как в вышеприведенной формуле, ибо там работает IntPower, который есть умножение), так и на сложении.
------------ Дoбавленo в 09.49:
Ыще
#pas
TRY
if cnt > 0 then begin
dtReal(Fd, FSP^);
dec(cnt);
while cnt > 0 do begin
dec(FSP); // Не правда !!! Сначала использование, а потом DEC
dtReal(FItem, FSP^);
AddMTData(@FItem, @Fd, tmp);
FreeData(@Fd);
Fd := FItem;
dec(cnt);
end;
end;
FItem := Fd;
_ReadData(FItem,self.X[i]);
FINALLY
FreeData(@Fd);
END;
if _IsNULL(FItem) then begin Err := 1; exit; end;
// Сначала INC (и где он ???), а потом запись
FSP^ := ToReal(FItem);
-- два раза.------------ Дoбавленo в 09.53:
Ыще
#pas
cnt := PInteger(FPC)^;
inc(FPC, sizeof(FPC)); // чего-чего ???
-- два раза.------------ Дoбавленo в 10.34:
Ыще
#pas
dtString(FItem, s);
if not _IsNull(Fd) then begin
AddMTData(@FItem, @Fd, tmp);
end;
Очень хочется спросить, а где под условием FreeData(@Fd); Fd := Fitem;...
Но не буду.
Ибо от этого геморроя надо избавляться по любому.
Он же, собака, оказывается -- более навороченный, чем в оригинальном MathParse...
------------ Дoбавленo в 10.58:
Ыще
#pas
i := Str2Int(Token)-1;
if i=-1 then begin
WriteProgB(CmdRead);
WriteProgB(255);
end else if i<FDataCount then begin
-- сей код несколько бессмысленен.Достаточно:
#pas
i := Str2Int(Token)-1;
if i<FDataCount then begin
-- ИБО: byte(-1)=255
карма: 9

0
Разработчик
Ответов: 4698
Рейтинг: 426
#83: 2014-06-30 16:03:18 ЛС | профиль | цитата
Galkov писал(а):
Дельфячья строка гарантирует нулик за своим "концом" (для совместимости со всякими другими системами, например WinApi).

А фпцшная?
Galkov писал(а):
Под Дельфи эти супер проверки тупо НЕ НУЖНЫ (зачем ты их там оставил?). Спрашивается, зачем напрягать как компилятор, так и процессор.

Я их с MathParse перенес и не трогал. Слышал, что так сделано потому, что в дельфи то как раз исключения нормально обрабатываются, а в FPC падает всегда. Вот поэтому эти проверки и ограждают от падений. Если бы не это, я бы всегда использовал только исключения, ибо удобнее в разы.
Galkov писал(а):
// Не правда !!! Сначала использование, а потом DEC

Цэ не баг, цэ фича!

Это хитрые оптимизации Если ты заметил, выше идет такой код:
#pas
dtReal(Fd, FSP^);
dec(cnt);
dec(CNT), не FSP, таким образом в цикле прежде чем считать еще одно значение, надо СНАЧАЛА применить dec(FSP), а потом уже считывать. И поэтому в конце не нужен inc(FSP), ибо уже указатель в положении последнего считанного элемента (который по сути должен быть выкинут из стека, но зачем лишний раз напрягаться? Лучше же взять и перезаписать его, не трогая указатель )
Galkov писал(а):
inc(FPC, sizeof(FPC)); // чего-чего ???

А это да. Поправил у себя. И ведь, собака, работает же верно, ибо на x86 sizeof(pointer) = sizeof(integer)
Galkov писал(а):
Очень хочется спросить, а где под условием FreeData(@Fd); Fd := Fitem;...

Не заглядывая в код: по-моему там две переменных, которые в стеке, и одна линкуется к другой через .ldata, после чего уже идет динамически выделенная память в AddMTData. Поэтому можно очистить только остаточный хвост после второй переменной, а первый .ldata подчистится вместе со стеком.
В любом случае заранее добавлю просчет количества элементов в цепочке и просто динамическим массивом буду выделять.
Galkov писал(а):
-- сей код несколько бессмысленен.

Код, может, и бессмысленен, но лучше явно показать, что здесь идет расчет на то, что может использоваться при выполнении результат предыдущих вычислений. Если условия не будет, после правок кода сразу и не разберешься, почему %0 перестал обрабатываться корректно.
------------ Дoбавленo в 16.03:
Кстати, начал работу над оптимизацией. Неужели все должно быть настолько сложно?
#pas
procedure THIMathParseEx.Level5(var res:TResult); // Логические операции
var op: char;
r: TResult; //промежуточный результат.
allConst: boolean; //целиком ли выражение - константа
begin
r.isConst := False;
Level6(res); {$ifdef F_P} if Err>=0 then exit; {$endif}
if res.isConst then begin
r := res;
allConst := True;
end else begin
allConst := False;
end;
while (Token = 'and')or(Token = 'or')or(Token = 'xor')do begin
op := Token[1];
GetToken; Level6(res); {$ifdef F_P} if Err>=0 then exit; {$endif}
if res.isConst then begin
if not r.isConst then begin
r := res;
case op of
'a': WriteProgB(CmdAnd);
'o': WriteProgB(CmdOr);
'x': WriteProgB(CmdXor);
end;
end else begin
case op of
'a': r.value^ := (r.value^ <> 0) and (res.value^ <> 0);
'o': r.value^ := (r.value^ <> 0) or (res.value^ <> 0);
'x': r.value^ := (r.value^ <> 0) xor (res.value^ <> 0);
end;
SetLength(FProgram, Length(FProgram) - sizeof(Real) - 1);
end;
end else begin
allConst := False;
case op of
'a': WriteProgB(CmdAnd);
'o': WriteProgB(CmdOr);
'x': WriteProgB(CmdXor);
end;
end;
end;
res := r;
r.isConst := allConst;
end;
карма: 10
0
Ответов: 9906
Рейтинг: 351
#84: 2014-06-30 17:22:15 ЛС | профиль | цитата
Assasin писал(а):
А фпцшная

А куда бы они делись нафиг.
В этом вообще нет никаких сомнений.

Assasin писал(а):
Я их с MathParse перенес и не трогал

Трогал. Я тебе привел свой код для CmdDiv, с условной компиляцией.
А ты ее убрал.
Не надо было убирать.

Assasin писал(а):
Если бы не это, я бы всегда использовал только исключения

Просто я не умею портировать err.pas под FPC, чтобы поймать Exception.
Ходят упорные слухи, что кто-то на форуме умеет.
Но мне в лом разбираться во внутренних кишках этого безобразия...

Assasin писал(а):
Если ты заметил, выше идет такой код

Все я заметил. Два раза.
И сделал Вывод - Твой код ошибочный. Смотри внимательней.


Assasin писал(а):
по-моему там две переменных, которые в стеке, и одна линкуется к другой через .ldata, после чего уже...

Чего это Вы, всегда, так сложно объясняете простые вещи....
При исполнении AddMTData - создается динамическая копия от второго аргумента, которая ставится в хвост первому аргументу.
Хвостов получается ДВА.
Кто второй убивать будет, Пушкин, что ли.

Assasin писал(а):
но лучше явно показать, что здесь идет...

Это твои человеческие проблемы.
Вот этими, человеческими средствами и разрешай эти проблемы. Все тебе спасибо скажут.
А не исполняемыми байтами в коде пользователя.

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



карма: 9

0
Ответов: 824
Рейтинг: 138
#85: 2014-06-30 17:55:30 ЛС | профиль | цитата
[flood]
Galkov писал(а):
Ни один Инженер (вменяемый, разумеется) не будет ставить лишние детали, из-за того что так лучше смотрится (читается, понятнее).
Уверяю тебя, проблем с понимаемостью в электронике - ничуть не меньше.
Не так давно,в советские времена, на крупных предприятиях, инженера заранее закладывали в изделия народного хозяйства "избыточные детали". А через годик делали "усовершенствование" изделия, вбрасывали эти "избыточные детали". В итоге - удешевлении производства, экономия материалов, трудозатрат, увеличение производительности, а "рационализаторам" - премии, медали, почетные грамоты, повышение, квартиры в неочереди и т.п. [/flood]
карма: 1

0
Ответов: 9906
Рейтинг: 351
#86: 2014-06-30 18:06:02 ЛС | профиль | цитата
[flood]Было-было.
Это "искусство" передавалось в курилках
[/flood]

карма: 9

0
Ответов: 824
Рейтинг: 138
#87: 2014-06-30 18:11:16 ЛС | профиль | цитата
[flood]И главное! - ВСЕ они были абсолютно вменяемы! [/flood]
карма: 1

0
Ответов: 9906
Рейтинг: 351
#88: 2014-06-30 19:09:27 ЛС | профиль | цитата
[flood]Но не Инженерами с большой буквы. А с маленькой
А домашнее все по чертежам тех конструкторов, что на низкой зарплате
Которых и конструкторами нельзя назвать. Как и те деньги - зарплатой (с) Жванецкий
[/flood]
карма: 9

0
Разработчик
Ответов: 4698
Рейтинг: 426
#89: 2014-06-30 19:28:09 ЛС | профиль | цитата
Galkov писал(а):
Трогал. Я тебе привел свой код для CmdDiv, с условной компиляцией.
А ты ее убрал.
Не надо было убирать.

Хм, и правда, прошу прощения, почему-то в голове отложилось, что код писался методом копипасты, значит и правок условной компиляции не было.
Galkov писал(а):
Все я заметил. Два раза.
И сделал Вывод - Твой код ошибочный. Смотри внимательней.

Не понимаю, что не так. Тестовые формулы проходит верно (например -1 * func(1, 2, 3)). Сам уже в который раз провожу построчную отладку - все правильно работает. Для примера возьмем cnt = 3, stack (пусть растет вправо) = 3 2 1.
1. В начальный момент FSP указывает на 1. Поэтому когда мы загоняем значение FSP^ в TData, мы считываем единицу.
2. Уменьшаем cnt на 1, т.к. один аргумент мы уже считали.
3. Потом начинается цикл. FSP по-прежнему указывает на первый аргумент (единицу).
4. Чтобы считать следующий аргумент, уменьшаем FSP, переходя к числу 2 (второй аргумент).
5. Загоняем аргумент в TData.
6. Уменьшаем cnt на 1. cnt = 1.
7. cnt > 0 = True, продолжаем цикл, уменьшаем FSP, теперь FSP^ = 3 (третий аргумент).
8. Считываем его и загоняем в TData.
9. Уменьшаем cnt, cnt = 0
10. Цикл кончился, FSP остался на третьем аргументе (тройка).
11. Происходит считывание данных с внешней точки (не затрагивает стек).
12. Пишем FSP^ := <результат запроса>.
13. Имеем на стеке только одно число - результат запроса с внешней точки.

Вопрос: что не так?
карма: 10
0
Ответов: 9906
Рейтинг: 351
#90: 2014-06-30 22:55:50 ЛС | профиль | цитата
Кажется, мне надо принести извинения (надо было, все-таки, три раза замечать)
Был неправ. Готов искупить и загладить

#pas
dtReal(Fd, FSP^);
dec(cnt); /// Вот тут я сбойнул !!! Думал, что это dec(FSP)
while cnt > 0 do begin
dec(FSP);
dtReal(FItem, FSP^);
Но я по сопротивляюсь еще немного...
Вариант cnt=0 у нас допустим
Для CmdUNFunc, вроде бы - ДА
И чего будет

#pas
CmdUNFunc: // name()
begin
s := ReadProgS;
cnt := PInteger(FPC)^;
inc(FPC, sizeof(integer));
dtString(FItem, s);
_ReadData(FItem,self.X[_prop_ExtNames-1]);
if _IsNULL(FItem) then begin Err := 1; exit; end;
FSP^ := ToReal(FItem);
end;
Это же неправильно



------------ Дoбавленo в 22.55:
Assasin писал(а):
Кстати, начал работу над оптимизацией. Неужели все должно быть настолько сложно?

Хмм.........

Мне, пока, очень не хотелось бы в кодах использовать знание о структуре TResult.
Мало ли чего еще в голову придет на этом Высоко-Интеллектуальном пути....
Пущай у нас будут методы основного класса, имеющие аргументом TResult.
И они, методы (а не мы) знают про FProgram, и как из него чего добыть, или удалить.

Ну твой-то вариант -- не такой уж смертельный
#pas
procedure THIMathParseEx.Level5(var res:TResult); // Логические операции
var op: char;
rs: TResult; //промежуточный результат.
begin
Level6(res); {$ifdef F_P} if Err>=0 then exit; {$endif}
while (Token = 'and')or(Token = 'or')or(Token = 'xor')do begin
op := Token[1];
GetToken; Level6(rs); {$ifdef F_P} if Err>=0 then exit; {$endif}
if isConst(res) and isConst(rs) then begin
case op of
'a': cstVal(res)^ := (cstVal(res)^<>0) and (cstVal(rs)^<>0);
'o': cstVal(res)^ := (cstVal(res)^<>0) or (cstVal(rs)^<>0);
'x': cstVal(res)^ := (cstVal(res)^<>0) xor (cstVal(rs)^<>0);
end;
delConst(rs); // Удаляем из программы константу, на которую указывает rs
end else begin
setVar(res); // Обзываем res - Переменной
case op of
'a': WriteProgB(CmdAnd);
'o': WriteProgB(CmdOr);
'x': WriteProgB(CmdXor);
end;
end;
// Здесь, res - уже должен быть в полной готовности
end;
end;

А хочется, ведь - большего:
#pas
procedure THIMathParseEx.Level5(var res:TResult); // Логические операции
var op: char;
rs: TResult; //промежуточный результат.
begin
Level6(res); {$ifdef F_P} if Err>=0 then exit; {$endif}
while (Token = 'and')or(Token = 'or')or(Token = 'xor')do begin
op := Token[1];
GetToken; Level6(rs); {$ifdef F_P} if Err>=0 then exit; {$endif}
if isConst(res) and isConst(rs) then begin
case op of
'a': cstVal(res)^ := (cstVal(res)^<>0) and (cstVal(rs)^<>0);
'o': cstVal(res)^ := (cstVal(res)^<>0) or (cstVal(rs)^<>0);
'x': cstVal(res)^ := (cstVal(res)^<>0) xor (cstVal(rs)^<>0);
end;
delConst(rs); // Удаляем из программы константу, на которую указывает rs
end else
if isConst(res) and (not isConst(rs)) then begin
setVar(res); // Обзываем res - Переменной
case op of
'a': begin if cstVal(res)^<>0 then delConst(res)
else WriteProgB(CmdAnd); // (false and X) ???
end;
'o': begin if cstVal(res)^= 0 then delConst(res)
else WriteProgB(CmdOr); // (true or X) ???
end;
'x': begin delConst(res);
if cstVal(res)^<>0 then WriteProgB(CmdNot);
end;
end;
end else
if (not isConst(res)) and isConst(rs) then begin
case op of
'a': begin if cstVal(rs)^<>0 then delConst(rs)
else WriteProgB(CmdAnd); // (X and false) ???
end;
'o': begin if cstVal(rs)^= 0 then delConst(rs)
else WriteProgB(CmdOr); // (X or true) ???
end;
'x': begin delConst(rs);
if cstVal(rs)^<>0 then WriteProgB(CmdNot);
end;
end;
end else begin
case op of
'a': WriteProgB(CmdAnd);
'o': WriteProgB(CmdOr);
'x': WriteProgB(CmdXor);
end;
end;
// Здесь, res - уже должен быть в полной готовности
end;
end;

Ну что тут можно сказать....
Пока, только одно в голову приходит: Який же ты Лыцарь, колы голой сракой ежа не вбьешь
карма: 9

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)