Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Компилятор математических выражений

Автор: Глызин Дмитрий

Цели использования

В некоторых областях часто встречается ситуация, когда требуется вычислять значения функций, задаваемых непосредственно во время работы программы. Иногда для этого достаточно создания интерпретаторов, которые производят как анализ, так и вычисление выражения средствами языка высокого уровня.

Однако в случаях, когда на первое место среди качеств программы выходит ее быстродействие, такой вариант становится неприемлемым. Как раз для приложений, производящих длительные вычисления, и был создан данный модуль, анализ формулы в котором производится так же, как и в интерпретаторах (благодаря однократности действия оно не оказывает влияния на скорость), но ее расчет при конкретных значениях переменных происходит с той же (либо большей) скоростью, что и при вызове обычных функций Delphi.

Возможности

  • Проверяется корректность введенного выражения.
  • Вычисляются правильно составленные выражения, содержащие бинарные операции +, -, *, /, ^, любые скобки, функции sin, cos, tg, ctg, exp, ln, lg, числовые константы типа extended (с точкой в качестве десятичного разделителя), и переменные произвольной длины, состоящие из букв любого алфавита и цифр.
  • Одинаковые символы в разных регистрах считаются идентичными.
  • Если аргументом функции является переменная либо константа, то их не обязательно заключать в скобки.

Пример:


-(x+cosy)/Exp[z]+LN {sin пеРеменная1-tg 3.14}

Ограничения текущей версии

В ситуациях, когда входному выражению соответствует обратная польская запись вида:

a b c d e f g h i  + + + + + + + + ,

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

Кроме того, для нормальной работы придется отключить Tools/Debugger options/Language Exceptions/Stop on Delphi Exceptions, иначе будет довольно утомительно: при анализе исключения возникают десятками.

Суть действий модуля

В памяти, соответствующей переменной типа "массив байтов", создается машинный код, соответствующий входной строке, после чего переменной типа "function:extended" присваивается адрес начала массива.

Использование модуля

1. Заводим переменную типа TFormula:


TFormula = record
  CS: CodeSeg; // массив с кодом
  DS: DataSeg; // массив с переменными и константами
  proc: tproc; // вызываемая функция
end;

var
  formula1: tformula;

2. Вызываем процедуру компиляции кода, в которой указываем нашу formula1, список имен используемых в ней переменных, и, конечно, входную строку.

3. Для вычисления значения функции в formula1.DS записываем значения переменных в том порядке, в котором их имена фигурировали в списке (при этом важно изменять только первые 0..число переменных-1 элементы DS, т.к. в последующих элементах хранятся значения констант из входной строки), а затем вызываем formula1.proc, которая и возвратит искомое значение.

Информация более конкретного характера содержится в самом модуле.

Использованные идеи и алгоритмы

  • Алгоритм Эрли проверки корректности входной строки.
  • Упрощенный вариант алгоритма Дейкстры перевода в обратную польскую запись на основе стека с приоритетами.
  • Способ формирования кода в памяти из программы Сергея Втюрина.
  • Методы вычисления различных математических функций из открытых исходников модуля Math.

Скачать проект Compiler.zip (25K)

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay