Каков наилучший способ оценить любое пользовательское математическое выражение, например
3+sqrt(5)+pow(3)+log(5)
Я знаю, что вложение Python в С++ может это сделать; есть ли лучший способ?
Спасибо!
Каков наилучший способ оценить любое пользовательское математическое выражение, например
3+sqrt(5)+pow(3)+log(5)
Я знаю, что вложение Python в С++ может это сделать; есть ли лучший способ?
Спасибо!
Boost.Spirit - библиотека анализатора С++.
Примеры:
Не знаю, почему "pow" имеет только один параметр, но с помощью библиотеки ExprTk можно получить следующее простое решение:
#include <cstdio>
#include <string>
#include "exprtk.hpp"
int main()
{
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
std::string expression_string = "3 + sqrt(5) + pow(3,2) + log(5)";
expression_t expression;
parser_t parser;
if (parser.compile(expression_string,expression))
{
double result = expression.value();
printf("Result: %19.15\n",result);
}
else
printf("Error in expression\n.");
return 0;
}
Нет никакого способа сделать это со стандартной библиотекой на С++, хотя есть много хороших алгоритмов синтаксического анализа, которые позволят вам оценивать выражения, подобные этим.
Если вы хотите получить некоторые ссылки на хорошие алгоритмы синтаксического анализа, рассмотрите главу 14 о синтаксическом анализе выражения в Программирование абстракций в С++ (бесплатно и доступно в Интернете!), или рассмотрите возможность поиска алгоритма Shynchstra для алгоритма. Оба алгоритма, упомянутые здесь, просты в реализации и позволят вам оценивать выражения с относительной легкостью.
Если вам интересны некоторые более хардкорные инструменты для оценки выражений, рассмотрите вопрос о flex
и GNU bison
, которые могут создавать мощные парсеры для этих выражений. Я считаю, что документация bison
даже показывает вам, как анализировать и оценивать арифметические выражения, поэтому вы могли бы выполнить свою работу за вас.
Надеюсь, это поможет!
muParserX - еще один синтаксический анализатор синтаксических выражений на С++.
Я написал простой, простой в использовании интерфейс для Lua для оценки арифметических выражений из C (и С++, конечно). См. http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#ae. См. Также Библиотека OpenSouce C/С++ Math parser Library и Что такое быстрый математический парсер C или Objective-C?
Отформатируйте строку следующим образом:
#include <boost/lexical_cast.hpp>
#include <string>
#include <math.h>
extern "C" {
std::string evaluate() { return boost::lexical_cast<std::string>(3+sqrt(5)+pow(3)+log(5)); }
}
Вызвать компилятор С++ для компиляции вышеуказанного кода в общую библиотеку. Затем загрузите эту общую библиотеку, разрешите адрес evaluate
, вызовите его и получите результат.
Здесь подход, написанный для последних версий Boost Spirit: http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html
Я разработал простой синтаксический анализатор на С++ и Java. В настоящий момент они обрабатывают только арифметические операторы+. -,/*, но нет причин, по которым они не могут быть расширены, чтобы вместить больше функций.
Эти простые примеры используют алгоритм маневрового двора для преобразования выражений в обратную польский нотацию, а затем еще один простой стековый алгоритм, чтобы фактически просчитать выражение.
Образцы кода можно найти здесь.
Lepton - это еще одна библиотека С++, которая может это сделать. В дополнение к анализу и оценке выражений, он также обладает некоторыми более продвинутыми способностями. Например, он может вычислять аналитические производные и может сделать некоторое базовое алгебраическое упрощение выражений. Библиотека довольно маленькая, и она с открытым исходным кодом (лицензия MIT).
При поиске в библиотеке для подобной задачи я нашел libmatheval. Кажется, это правильная вещь. К сожалению, GPL, что неприемлемо для меня.
Самый простой способ - использовать внешнюю библиотеку. Самый простой из них - TinyExpr. Он написан на языке C, поэтому его очень легко вызвать из С++. Кроме того, это только один исходный файл и один заголовочный файл. Очень легко интегрировать. Вы можете получить здесь.
Решение проблемы с вашим примером просто:
#include "tinyexpr.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Result: %f\n", te_interp("3+sqrt(5)+pow(3,2)+log(5)", 0));
return 0;
}
Я знаю, что вложение Python в С++ может сделать это
Вы могли бы это сделать, но для решения простой проблемы вы бы использовали огромную зависимость.