Подтвердить что ты не робот

Каков наилучший способ оценки математических выражений в С++?

Каков наилучший способ оценить любое пользовательское математическое выражение, например

3+sqrt(5)+pow(3)+log(5)

Я знаю, что вложение Python в С++ может это сделать; есть ли лучший способ?

Спасибо!

4b9b3361

Ответ 2

Не знаю, почему "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;
}

Ответ 3

Нет никакого способа сделать это со стандартной библиотекой на С++, хотя есть много хороших алгоритмов синтаксического анализа, которые позволят вам оценивать выражения, подобные этим.

Если вы хотите получить некоторые ссылки на хорошие алгоритмы синтаксического анализа, рассмотрите главу 14 о синтаксическом анализе выражения в Программирование абстракций в С++ (бесплатно и доступно в Интернете!), или рассмотрите возможность поиска алгоритма Shynchstra для алгоритма. Оба алгоритма, упомянутые здесь, просты в реализации и позволят вам оценивать выражения с относительной легкостью.

Если вам интересны некоторые более хардкорные инструменты для оценки выражений, рассмотрите вопрос о flex и GNU bison, которые могут создавать мощные парсеры для этих выражений. Я считаю, что документация bison даже показывает вам, как анализировать и оценивать арифметические выражения, поэтому вы могли бы выполнить свою работу за вас.

Надеюсь, это поможет!

Ответ 4

muParserX - еще один синтаксический анализатор синтаксических выражений на С++.

Ответ 6

Отформатируйте строку следующим образом:

#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, вызовите его и получите результат.

Ответ 8

Я разработал простой синтаксический анализатор на С++ и Java. В настоящий момент они обрабатывают только арифметические операторы+. -,/*, но нет причин, по которым они не могут быть расширены, чтобы вместить больше функций.

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

Образцы кода можно найти здесь.

Ответ 9

Lepton - это еще одна библиотека С++, которая может это сделать. В дополнение к анализу и оценке выражений, он также обладает некоторыми более продвинутыми способностями. Например, он может вычислять аналитические производные и может сделать некоторое базовое алгебраическое упрощение выражений. Библиотека довольно маленькая, и она с открытым исходным кодом (лицензия MIT).

Ответ 10

При поиске в библиотеке для подобной задачи я нашел libmatheval. Кажется, это правильная вещь. К сожалению, GPL, что неприемлемо для меня.

Ответ 11

Самый простой способ - использовать внешнюю библиотеку. Самый простой из них - 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 в С++ может сделать это

Вы могли бы это сделать, но для решения простой проблемы вы бы использовали огромную зависимость.