Quelle est la meilleure façon d'évaluer les expressions mathématiques en C++?
Quelle est la meilleure façon 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 faire ça; y a-t-il un meilleur moyen?
Merci!
11 réponses
coup de pouce.Spirit est une bibliothèque C++ parser.
exemples:
- dans sa distribution: classic version et current version (chercher "calc");
- on Rosetta wiki ;
- certains applications de l'utiliser.
Je ne sais pas pourquoi 'pow' n'a qu'un paramètre, mais en utilisant le ExprTk bibliothèque on peut dériver le suivant simple solution:
#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 disponible dans le commerce en C++, bien qu'il y ait beaucoup de bons algorithmes d'analyse là-bas qui vous permettront d'évaluer des expressions comme celles-ci.
si vous voulez des références sur les algorithmes d'analyse, pensez à regarder dans le Chapitre 14 sur l'analyse d'expression dans Abstractions de programmation en C++ (gratuit et disponible en ligne!), ou envisager d'examiner le triage de Dijkstra l'algorithme de . Les deux algorithmes mentionnés ici sont simples à mettre en œuvre et vous permettront d'évaluer les expressions avec une relative facilité.
si vous êtes intéressé par des outils plus hardcore pour évaluer les expressions, pensez à regarder dans les outils flex
et GNU bison
, qui peuvent construire des parseurs puissants pour ces sortes d'expressions. Je crois que la documentation bison
montre même comment analyser et d'évaluer des expressions arithmétiques, alors vous pourriez avoir votre travail est déjà fait pour vous.
Espérons que cette aide!
j'ai écrit un simple, facile à utiliser, front-end à Lua pour évaluer les expressions arithmétiques de C (et C++ bien sûr). Voir http://www.tecgraf.puc-rio.br / ~lhf/ftp/lua / #ae . Voir aussi OpenSouce C/C++ expression Mathématique parser et qu'est Ce qu'un rapide C ou Objective-C mathématiques de l'analyseur?
Lepton est une autre bibliothèque C++ qui peut faire cela. En plus de l'analyse et de l'évaluation des expressions, il a aussi quelques pouvoirs avancés. Par exemple, il peut calculer des dérivés analytiques, et il peut faire une simplification algébrique de base des expressions. La Bibliothèque est assez petite, et c'est open source (licence MIT).
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
j'ai développé un simple analyseur d'expression en C++ et Java. À l'heure actuelle, ils ne manipulent opérateurs arithmétiques +. - , / * mais il n'y a pas de raison pour qu'elles ne puissent pas être étendues à d'autres fonctions.
ces exemples simples utilisent l'algorithme shunting yard pour convertir les expressions en notation Polish inversée, puis un autre algorithme simple basé sur la pile pour evauler réellement l'expression.
Codedes échantillons peuvent être trouvés ici .
en cherchant une bibliothèque pour une tâche similaire, j'ai trouvé libmatheval . Semble être une bonne chose. Malheureusement, GPL, ce qui est inacceptable pour moi.
formater une chaîne comme celle-ci:
#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)); }
}
invoque 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
, invoquez-la et obtenez le résultat.
la façon La plus simple est d'utiliser une bibliothèque externe. Le plus facile que j'ai trouvé est TinyExpr . Il est écrit en C, donc il devrait être très facile d'appeler depuis C++. Aussi, c'est seulement un fichier source et un fichier d'en-tête. Très facile à intégrer. Vous pouvez l'obtenir ici .
résoudre votre problème d'exemple est juste:
#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 faire ça
vous pourriez faire cela, mais vous seriez en train de tirer dans une énorme dépendance pour résoudre un problème simple.