Quel est le meilleur moyen d'évaluer une expression mathématique personnalisée, par exemple
3+sqrt(5)+pow(3)+log(5)
Je sais que l'intégration de Python dans C++ peut le faire; Y a-t-il une meilleure façon?
Merci!
Boost.Spirit est une bibliothèque d'analyseurs C++.
Exemples:
Vous ne savez pas pourquoi 'pow' n'a qu'un paramètre, mais en utilisant la bibliothèque ExprTk , on peut obtenir la solution simple suivante:
#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;
}
Il n'y a aucun moyen de faire cela avec une bibliothèque standard prête à l'emploi en C++, bien qu'il existe de nombreux bons algorithmes d'analyse qui vous permettent d'évaluer des expressions comme celles-ci.
Si vous souhaitez des références sur de bons algorithmes d’analyse, jetez un œil au chapitre 14 sur l’analyse d’expression dans Programmation d’abstractions en C++ (gratuit et disponible en ligne!), Ou examinez L’algorithme de Dijkstra . Les deux algorithmes mentionnés ici sont simples à implémenter et vous permettront d’évaluer les expressions avec une relative facilité.
Si vous êtes intéressé par des outils plus sophistiqués pour évaluer les expressions, envisagez les outils flex
et GNU bison
, qui peuvent générer des analyseurs syntaxiques puissants pour ce type d'expressions. Je crois que la documentation bison
vous montre même comment analyser et évaluer des expressions arithmétiques, de sorte que votre travail pourrait déjà être fait pour vous.
J'espère que cela t'aides!
muParserX est un autre analyseur d'expression mathématique C++.
J'ai écrit à Lua une interface simple, facile à utiliser, permettant d'évaluer les expressions arithmétiques en C (et C++ bien sûr). Voir http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#ae . Voir aussi Analyseur d'expression mathématique OpenSouce C/C++ Bibliothèque et Qu'est-ce qu'un analyseur syntaxique rapide C ou Objective-C?
Lepton est une autre bibliothèque C++ capable de le faire. En plus d'analyser et d'évaluer des expressions, il possède également des capacités plus avancées. Par exemple, il peut calculer des dérivées analytiques et effectuer quelques simplifications algébriques de base des expressions. La bibliothèque est assez petite et open source (licence MIT).
J'ai développé un simple expression parser en C++ et Java. Pour le moment, ils ne traitent que des opérateurs arithmétiques +. -,/* mais il n'y a aucune raison pour qu'ils ne puissent pas être étendus pour accueillir davantage de fonctions.
Ces exemples simples utilisent l’algorithme de triage pour convertir les expressions en notation polonaise inversée, puis un autre algorithme simple basé sur une pile pour évaluer l’expression.
Des exemples de code peuvent être trouvés ici .
En cherchant dans une bibliothèque une tâche similaire, j'ai trouvé libmatheval . Semble être une bonne chose. Malheureusement, GPL, ce qui est inacceptable pour moi.
Voici une approche écrite pour les versions récentes de Boost Spirit: http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html
Le moyen le plus simple consiste à utiliser une bibliothèque externe. Le plus simple que j'ai trouvé est TinyExpr . Il est écrit en C, il devrait donc être très facile d’appeler à partir de C++. En outre, il ne s'agit que d'un fichier source et d'un fichier d'en-tête. Très facile à intégrer. Vous pouvez l'obtenir ici .
Résoudre votre exemple de problème est simplement:
#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;
}
Je sais que l'intégration de Python dans C++ peut le faire
Vous pourriez le faire, mais vous auriez une énorme dépendance pour résoudre un problème simple.
Formatez une chaîne comme ceci:
#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)); }
}
Appelez le compilateur C++ pour compiler le code ci-dessus dans une bibliothèque partagée. Puis chargez cette bibliothèque partagée, résolvez l'adresse de evaluate
, appelez-la et obtenez le résultat.