К списку форумов К списку вопросов
как текст преобразовать в функцию (Delphi)
Dr Alex
04.05.2004 - 21:32
Ещё такой вопросик:
Есть форма edit1, так вот, что нужно сделать, чтобы введённое 2*x^3+10*x воспринималось машиной как функция 2*x*x*x+10*x или что-то вроде???
archimag
1 - 04.05.2004 - 22:06
Ну, это полностью на твоей совести. Может, есть готовые компоненты, делающие это, но самому сделать тоже не очень сложно. Идея в том, чтобы написать класс, работающий как синтаксический анализатор и способный трактовать строку как функцию. Несложный пример приводит Страуструп, неплохой пример с аналитически взятием производной есть у Д.Кнута в 1-ом томе. Полезно самому разобраться. У меня где-то валяется подобный класс на С++, но, как я понимаю, ты пишешь в Delphi.
_van
2 - 05.05.2004 - 13:42
Поверь здесь этого никто незнает.
`
1 сказал не то что тебе нужно недостатки: каждый раз для вычисления значения функции происходит синтаксический разбор выражения (а вызовов может быть порядка 100000)и для произвольного случая работать небудет.
`
К сведению: недостатков лишен только компилятор.
Можешь попробовать так: задали в edit1 текст- генеришь файл-исходник dll, вызываешь из программы компилятор командной строки, потом используешь эту внешнюю dll функцию.
`
Но мой реальный совет не убивай на это время.
UE
3 - 05.05.2004 - 13:52
Мне кажется, что имеет смысл либо поискать готовые компоненты, либо посмотреть в сторону скриптовых языков (см. IActiveScript и т.д.).
archimag
4 - 05.05.2004 - 14:19
2van не согласен. Во-первых, синтаксический разбор проходит очень быстро, а во-вторых, его нужно сделать всего один раз, а полученную информация хранить например в виде дерева. Конечно, потери в производительности будут, но чего же вы хотели?.. и не факт, что это критический момент системы. А вот вариант с компилятором - совершенно не нужный геморрой.
Написать самому - это проще и быстрее, чем искать и разбираться в уже готовых решениях.
_van
5 - 05.05.2004 - 16:56
2 3 Конечно это выход "посмотреть в сторону скриптовых языков", Но по опыту работы с матрицей 100*100*100(трехмерная) это все-же не то что хотелосьбы(производительность падает на 2 порядка!).
2 4 аналогично, и вдобавок это сложно учесть все варианты и трудоемко написать хорошо.
`
Лучшее решение иметь уже откомпилированную функцию, но как я и сказал в 2 этого здесь никто не знает.
Если несогласны просветите пожалуйта, как вы представляете себе решение к примеру задачи рисования графика функции задаваемой в edit1?
archimag
6 - 05.05.2004 - 17:19
Ну, если оптимизация действительно так важна, то при наличие кое-каких познаний в asm и наличие свободного времени, можно написать небольшой компилятор, который по результатам синтаксического анализа будет генерировать машинный код (откомпилировать простую функцию - в общем-то, не так уж и сложно). Пожалуйста, выделяешь память, туда записываешь сгенерированный код, через указатель вызываешь функцию и т.д. Нечто подобное, я как-то делал из любопытства.
Но такая жесткая оптимизация обычно не очень-то и нужна.
Grigoriy
7 - 05.05.2004 - 17:28
и получишь маткад
_van
8 - 05.05.2004 - 20:55
archimag: да 6 это очень хорошее решение, но это очень трудоемкое решение!, опять же нужен компилятор командной строки асма:)- так как писать в машинных кодах на порядок еще более трудоемкая задача.
`
На экран нужно порядка 1024*100 просчетов(актуальный пример асцелирующий синус)
Ну как рисовать график функции из edit1- просветите плз ламерюгу!
_van
9 - 05.05.2004 - 20:58
<можно написать небольшой компилятор>
А зачем писать когда есть готовый с командной строки причем используемого тобой языка?
`
<Поверь здесь этого никто незнает>!
Сергей
10 - 05.05.2004 - 21:09
Почитай решение своей проблемы в описании паттерна interpreter
http://ooad.asf.ru/patterns/patterninfo.asp?id=27
archimag
11 - 05.05.2004 - 22:01
Сергей: по-моему, не очень полезная статья (слишком общая), разбор калькулятора у Страуструпа более понятен.
van: для простых задач (а это простая задача), не вижу разницы, как писать: на ассемблере или в машинных кодах, если сможешь сгенерировать ассемблерный код, то сможешь и машинный. Да и зачем тебе столько вычислений, для простого графика обычно достаточно точек 60.
Сергей
12 - 05.05.2004 - 22:21
Гм... На мой взгляд, как раз весьма подходящий вариант - во-первых, нет необходимости писать свой компилятор :) во-вторых, разобрав один раз выражение, строится дерево из объектов, которые будут производить вычисления почти что "в машинных кодах", т.е. ненамного медленнее, чем "оптимизированные" реализации; еще один плюс - проверенное временем решение :)
archimag
13 - 05.05.2004 - 23:08
Сергей: может ты и прав. На досуге почитаю повнимательнее. Просто, у меня, необходимости в сложном синтаксическом разборе не было, а строить иерархию классов для разбора простой формулы как-то излишне.
_van
14 - 06.05.2004 - 08:19
Ребята я не автор темы. Ссылка дельная- проработать бы если возникнет необходимость. Я так и непонял получится ли за 10 часов работы написать такой анализатор который незагнется для произвольного выражения:
sin(x^3.14*ln(abs(cos(e^x))+0.001))
Что-бы смотреть график любой функии, померещевшейся из-за угла?
`
А с оптимизацией согласен потеря линейная, а не на порядок как в случае интерпретатора.
Сергей
15 - 06.05.2004 - 11:07
[14] Про "десять часов" - думаю, вполне реально. Не вижу особой причины "загнуться" :)
Prapor
16 - 06.05.2004 - 11:24
есть в делфях такая функция. делали года 3 назад с ее 5 использованием прогу. но не помню как зовется, а исходник потерян. найди в нете исходники таких функций, их полно.
Prapor
17 - 06.05.2004 - 11:25
to: _van. ты случаем не из Сочи?
_van
18 - 06.05.2004 - 13:20
Нет из Воронежа :)
Serg
19 - 06.05.2004 - 17:07
Подобную весчь знакомый препод довел до совершенства еще года 4 назад, по ТрубоПаскаль. Если исходники не потерялись, доставлю.
мыло свое пришли
OGA
20 - 06.05.2004 - 21:14
Да уж....
с компилятором эт хорошо)))пробовал - медленно)))на разбор уходит уйма времени да и как бы ты его не хранил уже в разобранном виде, все равно уходит времени на порядок больше (слишком много ифов))))Решение в итоге нашел простое, просто отказался от разбора и дал пользователю стандартные функции (синус, косинус, тангенс, логарифмы и т.д.) пользователь может выбрать одну из перечисленных функций...
все функции в общем виде...например A*Sin(X*B+C),.. для большенства функций достаточно трех параметров (ну исключения всякого рода биномы - в которых можно использовать приближения и тож обойтись тремя параметрами)..
далее указываются функции для A, B, C или указывается значение если оно постоянно...
т.е. в итоге можно запросто промодулировать синусоиду или построить какой нить сногшибательный график...
кстати, можно превести любую формулу с определенной погрешностью к выражению типа A+Bx+Cx^2+Dx^3... (т.е. разбирается функция...вычисляеются производные и т.д....как построить такой ряд см курс вышей матиматики)
в итоге имеем ряд параметров загнанных в матрицу...и уж функцию написать что бы все летала, все сгребала - результаты выдавала...думаю плевое дело)))ну а степень приближения можно указывать и в диалоге с пользователем))))
_van
21 - 07.05.2004 - 17:54
Со степенью приближения к ряду эт я так понимаю бабушка надвое сказала?
Если для каждой заданой пользователем функции разбор делается один раз, то это нормально, неверю что удастся намудрить хотябы на 0,1секунды работы 386.
`
Насчет потерь на порядок я сказал неподумавши- всегда линейная потеря с неким коэффициентом.
`
Но кто досих пор несогласен что эффективней всего использовать внешнюю функцию, компилируемую компилятором командной строки из программы в .dll?
Сергей
22 - 07.05.2004 - 18:41
[20] После того, как текст разобран в сответствии с предложенным решением [10] (не вижу причин, по которым разбор выражения разумной сложности должен занять времени больше, чем, скажем, 0.1 секунда), вычисление по формуле не будет содержать "слишком много ифов" - оно вообще не будет их содержать. Напротив, результат будет более всего похож на набор указателей на функции, которые нужно выполнить, чтобы получить результат. По скорости исполнения едва ли будет сильно проигрывать "захардкоденой" реализации.
Sabrian
23 - 08.05.2004 - 14:28
Впринципе, если кому надо я могу поделится исходниками(Delphi) своего подобного парсера, из плюсов работа со стоками, массивами и переменными( любого типа), есть несколько стандартных функций работы со стороками, и несколько програмерских операций вроде in, as, is. Логические выражения.
Из-за всех этих наворотов скорость конечно не такая уж и высокая, но средненькое выражение на компе класса AXP 1800+ можно посчитать раз эдак 100K в сек.
lesha
24 - 08.05.2004 - 14:53
можно написать парсер, например с помощью библиотеки boost\spirit
Сool Ace
25 - 11.05.2004 - 09:59
Можно и без помощи,в любом случае работать будет очень быстро, если сделать так как написал Сергей, достаточно 1 раз разпарсить выражение, а потом пройтись по дереву из построенных во время парсинга объектов.

К списку вопросов на форуме Программирование

>>