Парсер математичних виразів на C#

Колись в універі треба було написати парсер математичних виразів. Писати його мені сподобалось, було цікаво, тепер хочу викласти його для загального користування.

Що це таке взагалі. Такий парсер це незамінна штука, якщо ваша програма має рахувати значення якихось виразів, і ці вирази треба задавати не в коді. А десь в інтерфейсі. Парсер приймає рядок символів типу sin(pi/3.8)*ln(100500)+arctg(2), парсить його і видає вам значення цього виразу. Тобто 9.58115271771543 :)

Тепер, що вміє конкретно цей парсер:
  1. Рахувати значення числового виразу;
  2. Рахувати значення виразу з довільною кількістю заданих змінних;
  3. Рахувати першу похідну виразу в точці;
  4. Рахувати другу похідну виразу в точці.

Поки що це все :). Завантажити парсер можна в кінці запису. Я час-від-часу шось доробляю, фікшу, тому цей запис постійно оновлюється, там в кінці ше є посилання на репозиторій, де можна завантажити вихідний код останньої версії. 

Що ше планую доробити:

  1. Унарний мінус. Зараз не можна написати щось типу -5*x+3. Унарний мінус не передбачений, тому таке не розпарситься. Доведеться викручуватись і самому робити його бінарним: 0-5*x+3. Колись виправлю; UPD 29.09.2015 — унарний мінус доробив Юра Прийма (2 курс, 2015 рік, інформатика). Правда не так, як мені хотілось, Юра просто заміняє «–» на «0–», що по-суті є костилем, але краще так, ніж ніяк :). Хотілось окремо описати унарний оператор «–» і те, як він має парситись.
  2. Задання функцій від багатьох аргументів зробив;
  3. Логарифм за будь-якою основою;
  4. Малювання графіків (це вже майже є);


Інтерфейс парсера

Є клас MathExpression, створюєте об’єкт цього класу, його конструктор приймає рядок, який треба розпарсити:

Список операторів, функцій і тд., які сприймає парсер:

  1. Додавання «+»;
  2. Віднімання «-»;
  3. Множення «*»
  4. Ділення «/»
  5. Піднесення до степеня «^»
  6. Корінь квадратний (sqrt);
  7. Дужки для надання пріоритету «(» і «)»
  8. Синус «sin»;
  9. Косинус «cos»;
  10. Тангенс «tg»;
  11. Котангенс «ctg»;
  12. Арксинус «arcsin»;
  13. Арккосинус «arccos»;
  14. Арктангенс «arctg»;
  15. Арккотангенс «arcctg»;
  16. Синус гіперболічний «sinh»;
  17. Косинус гіперболічний «cosh»;
  18. Тангенс гіперболічний «tgh»;
  19. Котангенс гіперболічний «ctgh»;
  20. Логарифм натуральний «ln»;
  21. Логарифм десятковий «lg»;
  22. Модуль «abs»;
  23. Функція знаку «sign»;
  24. Число пі «pi»
  25. Число е «e»
  26. В якості змінних можна використовувати майже всі букви лат. алфавіту. Не можна використовувати «е» (бо це константа), і ще декілька. Список букв для змінних: a, b, c, d, i, j, k, l, m, n, p, q, r, s, t, u, v, x, y, z.

В парсері є такі методи:

  1. double Calculate(); //рахує і повертає значення простого числового виразу (без змінних)
  2. double Calculate(double); //рахує значення виразу в точці
  3. double Calculate(params double[]); //рахує значення виразу від кількох змінних, значення змінних задаються через кому. Якщо першою у виразі зустрінеться змінна x, то парсер замінить всі ікси у виразі на те значення, яке ви передали першим, якщо другою буде змінна y, то всі ігрики заміняться на друге передане вами значення, і так далі. Якщо не ясно, нижче є приклади;
  4. double Calculate(params Var[]); //рахує значення виразу від кількох змінних, аргументами є об’єкти типу Var. Тип Var складається з двох проперть, name (string) і value (double), відповідно назва і значення змінної. У цьому методі можна явно задати, яка змінна чому має бути рівна. Приклади теж нижче;
  5. double Derivative(double); //рахує значення похідної виразу в точці
  6. double SecondDerivative(double); //рахує значення другої похідної виразу в точці


Приклади використання

Обчислення значення простого числового виразу:

Обчислення значення виразу із однією змінною, значення якої 2:

Обчислення значення виразу від двох змінних, одна = 2, інша 5.

Обчислення значення виразу від двох змінних, із явним заданням, що y=10, x=4.

Обчислення похідної виразу в точці x=0. Похідну рахує наближено, наприклад тут точне значення похідної має вийти 2, а обчислене виходить 2.0000001654807. Так, точність туфтова. Щось з цим зроблю.

Обчислення другої похідної при x=0:



Файли для завантаження

Поки що парсер досить сирий, і там ше є що доробляти, але я вирішив, що він вже достатньо непоганий, щоб показувати його на публіку :). Назвемо це версією 0.1.

  1. dll-бібліотека, готова для використання. Щоб підключити її, додайте у проект reference на цей dll-файл, і потім зробіть using PoohMathParser. Ну ви ж вмієте підключати бібліотеки?)
  2. репозиторій з вихідними файлами (обережно, бидлокод!)
12 березня 2014 о 09:14