интерпритатор математических выражений

  • Автор темы Norfonzor
  • Дата начала
N

Norfonzor

#1
Здрасте! собрал полезную програмку для постройки графиков неявновыраженых ф-ий, придумал интересный алгоритм построения ф-ий, ускоряющий построение в несколько тысяч раз, поэтому очень важно довести программу до ума.
проблема в следующем:
ф-ю необходимо вводить с формы edit, ф-ия вводится в формате стринг, ее необходимо преобразовать в переменные x и y и математический ф-ии
sin, cos, tg, ctg, ln,pow, arctg, arcctg. строка может вводится в формате "x+y+*x*y/1(2/(3/(x*y*y*pow(x,y)))+sin(x+y+1))"
проблема в том, что даже если прогонять через интерпретатор то нода прогонять только 1раз а не обновлять стринг-> переменные при построении ф-ии. тк происходит обращение к ф-е BBog_xy(x:real; y:real):real (с имеющимися x y, ф-ия должна вывести значениепосле подстановки значений x y в введеную пользователем ф-ю) к ф-ии BBog_xy будет 10000000000000+ обращений. и поэтому необходимо как то сделать конструкцию:

ввод строки fun
fun->переменные

а после множество раз обращение с имеющимися x,y и вывод ответов, таким образом чтобы сложный процесс интерпретирования не проходить вновь.

пожалуйста помогите!
 
P

Poseidon

#2
В JEDI есть интерпритатор. Хоть и не очень толковый, но хоть какой-то. Основные функции обрабатывает. По-моему там даже до 5 вложений, хотя могу ошибаться.
 
B

BurcevD

#3
Посмотри в инете на счет ПОЛИЗ! (ПОЛьская Инверсная Запись)
http://www.bguir.net/content/view/74/1/
вот кстати есть пример, в институте делали, немного доработаешь и все будет нормально =)
 

Вложения

N

Norfonzor

#4
понимаете в чем проблема, даже если я сделаю интерпретатор (впринцыпе у меня сть он только для паскаля но переделыть не сложно будет, я тоже когда его под себя переделывал, я не подозревал что столкнусь с проблемой про которую спрашиваю у вас) он мне не поможет! вот еще раз (последовательность нельзя менять! ) матрите:

ввод(st);
interpretator(st:string); (он как то должен запомнить порядок действий чтобы в последующем ему не приходилось все заново переводить строку в переменные)

ввод значений (x;y)
(т.е. значений должны вводиться после прохождения интерпритатора! и нельзя эту строку загружать вночь прохождением интерпретатора) в противном случаи у меня график будет строиться на 90% дольше а это недопустимо

мб есть другой способ перевода ф-ии?? скажем както через запись ее куданибудь в текстовый файл или еще как-нибудь? в паскале я сохранял ее в TPU файл как модуль, но пришлось с собой таскать компилятор не удобно это. как еще можно сделать??
 
P

Poseidon

#5
Что-то не совсем понял. У тебя есть функция (как в примере x+y+*x*y/1(2/(3/(x*y*y*pow(x,y)))+sin(x+y+1)) ). Есть некие значения переменных х и у. Прогоняешь интерпритатором эту функцию, сразу подставляя значения. Получается на один прогон - один расчет. Т.е. функция интерпритатора должна иметь вид примерно такой
function interpretator(func:string; x,y: integer): real

По другому никак. Даже если не использовать интерпритатор, а задать конкретную формулу, то все-равно получится что для каждой пары x,y нужно проводить отдельный расчет. Единственное, что может снизить скорость расчетов, это преобразование функции расчета из строкового вида и непосредственно функцию. Тут уже нужно оптимизировать так, что бы было менше тактов процессора задействовано.
 
N

Norfonzor

#6
те я понимаю что невозможно сделать код так чтобы перевод ф-ии из стринг в переменные осуществлялось интерпретатором всего 1 раз, а x y огромное множество раз. т.е. нельзя сделать так чтобы вначале расчитывалась ф-ия а потом в нее значения подставлялись множество раз, не затрагивая первый шаг перевода строки в переменные
а как же работают современные программы для построения графиков? я чтото сомневаюсь что они для каждого действия прогоняют интерпретатор.
как тогда в них организован парсер?
 
P

Poseidon

#7
т.е. нельзя сделать так чтобы вначале расчитывалась ф-ия а потом в нее значения подставлялись множество раз, не затрагивая первый шаг перевода строки в переменные
Нельзя!

а как же работают современные программы для построения графиков?
Так и работают. Скорее всего у них интерпритатор оптимизирован, поэтому и получается быстро. Можно покопать в сторону RemObjects Pascal Script и компилировать функцию расчета "на лету".
 
P

Poseidon

#8
В общем, вспомнил про очень хорошую штуку, которая появилась только в 2005 среде и дельше. Называется inline.
inline нужно использовать там, где компилятор может подставить вычесляемое функцией значение вместо вызова функции. То есть у тебя есть функция, которая возвращает значение 2+2, тогда компилятор в месте вызова функции не будет ее вызывать, а сразу подставит значение.:
inline int sum(int a, int B){return a+b;}
int f = sum(2,2);
в скомпилированом коде будет так: int f = 4;
Разбирайся
 
E
#9
Можно воспользоваться уже существующими и прошитими в системе интерпретаторами, бейсики яваскрипты, работают быстро, и как раз то что вам надо, "интерпретируют" 1 раз, далее подкидываете аргументы.
 
N

Norfonzor

#10
где можно их найти и в код делфи можно вставить?? мб как-то модулем он идет??
 
N

Norfonzor

#12
((( ничего не нашел, я думаю проще самому написать интерпритатор чем искать его в сети, да и тем более я не знаком со всеми этими технологиями, знаю только дэлфи на уровне 1-2го курса института
 
E
#13
емае, с таким успехом, я думаю вы напишете интерпритатор ... хренли его искать в поисковик вбейте 3 слова и все - полный вперед ...
 
N

Norfonzor

#14
нашел интерпритатор под делфи "CalcExpress" от AidAim Software. не могу его установить ;) вообще не знаю как им пользоваться, как его вставить в мой код??

архив
http://webfile.ru/3243773

....
ввод строки fun
....
....
множественное обращение к этой ф-ии с значениями x и y
BBogxy(x ,y); (ввод x и y) если при подстановке в ф-ию значений, результат меньше 0.01 то строить точку
....
....
как это организовать?
 
N

needDrivers

#16
Тебе просто надо распарсить строку в байт код, а уже байт код интерпретировать много раз, который и будет читать переменные x и y.
И не надо каждый раз разбирать строку.
 
N

needDrivers

#18
Я бы использовал связку bison + flex. В принципе задача не сложная, но если никогда не пользовались bison'ом, то будет сложновато.

x+y+x*y/1*(2/3)
В байт-коде эта строка получиться примерно такой:
Код:
push x
push y
add
push x
push y
mul
push 1
div
push 2
push 3
div
mul
add
Результат выражения будет на вершине стека.

В общем, не знаю как правильно всё это объяснить. :)

http://ru.wikipedia.org/wiki/GNU_bison
http://pfzim.ru/blog/article/20


http://ru.wikipedia.org/wiki/%D0%91%D0%B0%...%BA%D0%BE%D0%B4
 
E
#19
Ну это больше похоже на асемблер ... да и вопрос то в том какой механизм для "распарсивания", а уж в куда - это десятое дело.
 
N

needDrivers

#20
Не совсем понял вопрос.
Пишешь грамматику для бисона, скармливаешь ему, он создаёт по ней исходник парсера, через этот парсер прогоняешь "математические выражения" и на выходе получаешь байт-код. А уже байт-код стравливаешь своему интерпретатору.

result = interpretate(bytecode, x, y);

Грамматика для бисона примерно такая:
Код:
line	: expr				{ pop result } // верхнее значение в стеке - результат
| 						{ result 0} // пустая стока - результат = ноль
;
expr	: T_CONST				{ push число } // положить в стек число
| expr '+' expr			{ add } // суммировать два верхних значения в стеке заменив их результатом
| expr '*' expr			{ mul } // перемножить два верхних значения в стеке заменив их результатом
;