IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez C++ Discussion :

[C++][Source] Interpréteur d'expression mathématique


Sujet :

Contribuez C++

  1. #1
    Membre éprouvé
    Avatar de Gabrielly
    Inscrit en
    Juin 2004
    Messages
    722
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 722
    Points : 1 128
    Points
    1 128
    Par défaut [C++][Source] Interpréteur d'expression mathématique
    Bonjour,

    Je voudrais vous faire partager mon interpréteur d'expression personnel mais c'est un code C++ dont voici ce qu'il est capable de faire.

    Vous pouvez saisir une expression de type fonction comme : f ( x , y ) = x ^ 2 + sin ( y )
    ou bien g ( x , y , z ) = x / sqrt( 1 + y ^ 3 + ln ( 5 * z ) )
    ou encore v ( t ) = r * sin( w * t + k )
    où les variables r, w et k sont préalablement définis comme des expressions de type variable du genre
    r = sqrt( 2 / pi ), w = 15, k = e^( -10 ) avec pi et e des constantes
    déjà reconnus comme constantes standards de 3.1415927... et 2.718182...
    (vous n'avez pas à les définir.)
    Vous pouvez saisir des fonctions de fonctions comme : h ( x ) = f( x - 1 , x + 1 ) + r * pi * sin( g( x + 1 , x ^ 2 , -x ) + pi / 4 )
    où f() et g() sont préalablement définis tel que ci-haut.
    Dans sa première version c'était un code pur C++ standard, mais j'avais perdu les sources.
    Alors j'ai refais un code plus propre et plus puissant capable d'analyser une expression avant son évaluation et gérant le mécanisme d'exception. Elle peut également évaluer des expressions avec nombres complexes tel que des z = a + b*i ou bien des 3 + 4i.

    J'ai profiter de la souplesse qu'offre la classe CString pour la manipulation des chaînes ce qui suppose qu'elle demande la présence des MFC.

    Voici la hiérarchie de mes principales classes templates

    CMcnExpression<T> : comprend toutes les expressions élémentaires de bases et définit et maintient une table des expressions globales.

    CMcnLexical<T> : se charge de faire l'analyse lexicale d'une expression et de donner la nature de chaque symbole. Elle dérive de la précédente classe.

    CMcnSyntaxic<T> : se charge de faire l'analyse syntaxique d'une expression et de savoir si elle est correctement écrite avec toute les imbrications, les références et les récursivités possibles entrées fonctions ou variables. Elle dérive de la précédente classe.

    CMcnVariable<T> : c'est l'objet variable proprement dite comme dans une expression simple comme "x = 2 / 3 + sqrt(pi)". Elle dérive de la précédente classe CMcnSyntaxic<T>.

    CMcnFunction<T> : c'est l'objet fonction proprement dite comme dans une expression comme "P(x) = x^5 + 3 * x ^ 4 + 2". Elle dérive de la précédente classe CMcnSyntaxic<T>.
    Voici un code simple d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    MCN::Math::CFunction g;
     
    if ( g.SetFunction("P(x) = x^5 + 3 * x ^ 4 + 2") )
    {
     
           double res = g(1);
           res = g(3.2);
           res = g(23.345);
    }
    Voici un code peu complexe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    MCN::Math::CFunction g;
    g.SetFunction("B(x) = x^5 + 3 * x ^ 4 + 2");  // une exception est lancé en cas d'erreur
     
    MCN::Math::CVariable v1;
    v1.SetVariable("A = sqrt(pi / 2)  + 1");
     
    MCN::Math::CVariable v2;
    v2.SetVariable("W = 2 * pi");
     
    MCN::Math::CFunction f;
    f.SetFunction("f(t) = A * sin ( W * t + B(t) )");
     
    double res = f(0);  // au temps t = 0
    res = f(2.5);  // au temps t = 2.5s
    res = f(10); // au temps t = 10s
    Toutes ces expressions peuvent être des input faits par l'utilisateur.
    On peut même créer sa propre calculatrice performante et tracer des courbes et des surfaces.

    Je vous envoie les sources. La version de mon Visual Studio est 2008
    Il s'agit d'une dll, Mcn.Math.dll, vous la compilez. Mais vous devez changer quelques paramètres du projet pour que la compilation passe.

    Vous n'avez besoin que d'un seul fichier header "Mcn.Math.h" qui comprend tous les fichiers en têtes dont vous avez besoin. Ainsi que de sa librairie Mcn.Math.lib


  2. #2
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Bonjour,

    J'aime bien le code et l'architecture de ton interpréteur, il permet de faire des choses que je n'avais même pas encore pensé à implémenter comme le support des nombres complexes la possibilité de définir des fonctions (car j'en ai également réalisé un, source disponible ici). En fait, pour la dernière si, mais pas je n'ai pas pensé à cette méthode. J'ai tout de suite pensé à quelque chose de plus complexe comme supporter un langage de script, perso ou existant (j'ai pensé à Python), alors que, bien que moins puissante, ta méthode peut se révéler très utile et efficace dans bon nombre de cas . Pour la première, je crois que je vais laisser parce que R suffit dans la majorité des cas où a besoin d'un interpréteur mathématique. Sinon pourquoi ne pas pas supporter les quaternions aussi .

    Merci pour cette source et a+.

  3. #3
    Membre éprouvé
    Avatar de Gabrielly
    Inscrit en
    Juin 2004
    Messages
    722
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 722
    Points : 1 128
    Points
    1 128
    Par défaut
    Voici un exemple d'utilisation de mon interpréteur d'équation.
    Je crée un projet simple de type "console application" avec support des MFC
    L'entrée principale de l'application est du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    // The one and only application object
    CWinApp theApp;
     
    using namespace std;
     
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    	// initialize MFC and print and error on failure
    	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    	{
    		// TODO: change error code to suit your needs
    		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
    		return 1;
    	}
     
                 // TODO: code your application's behavior here.
                 return 0;
    }
    Ensuite j'inclus le fichier "Mcn.Math.h" dans le "stdafx.h" du projet console
    Il s'agit d'un chemin relatif à partir du projet console pour atteindre mon header
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #include "..\Mcn.Math\Mcn.Math.h"
    Je vais dans les paramètres du projet console
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Properties > Configuration Properties > Linker > Input > Additionnel Dependencies > ..\debug\Mcn.Mathd.lib
    Je reviens sur le fichier source principal de mon projet est j'écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    // Calculator.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "Calculator.h"
    #include "conio.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    
    // The one and only application object
    CWinApp theApp;
    
    // déclare l'unique table des expressions utilisant des nombres réels "double" 
    MCN_DECLARE_GLOBAL_EXPRESSION_TABLE(double)
    
    using namespace std;
    
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    	// initialize MFC and print and error on failure
    	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    	{
    		// TODO: change error code to suit your needs
    		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
    		return 1;
    	}
    
               //...
    La déclaration en rouge de la table des expressions globales pour tout le projet est très importante. Cette ligne de code n'intervient qu'une seul fois dans tout le projet. Elle permet de disponibiliser toutes les expressions qui interviennent dans le projet.

    La suite du code dans _tmain() est l'exemple d'utilisation d'une fonction à une variable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
                 MCN::Math::CFunction g;
    
    	if ( g.SetFunction("P(x) = x^5 + 3 * x ^ 4 + 2") )
    	{
    		cout << "P(x) = x^5 + 3 * x ^ 4 + 2" << endl << endl;
    		cout << "P(1) = " << g(1.0) << endl;
    		cout << "P(3.2) = " << g(3.2) << endl;
    		cout << "P(-5) = " << g(-5.0) << endl << endl << endl;
    	}
    Voyez comment j'indique g(1.0) et non g(1) pour indiquer que 1 est un double. Pay attention!!!
    Le foncteur g s'identifie à la fonction P(x) qui s'incrit dans la table des expressions globales.

    La suite du code dans _tmain() est l'exemple d'utilisation des variables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	MCN::Math::CVariable v1;
    	v1.SetVariable("A = sqrt(pi / 2)  + 1");
    
    	MCN::Math::CVariable v2;
    	v2.SetVariable("W = 2 * pi");
    
    	cout << "A = sqrt(pi / 2)  + 1" << endl;
    	cout << "W = 2 * pi" << endl << endl;
    
    	cout << "A = " << v1 << endl;
    	cout << "W = " << v2 << endl;
    Les variables v1 et v2 s'identifient aux variables A et W qui s'incrivent dans la tables des expressions globales.

    La suite du code dans _tmain() est l'exemple d'utilisation de fonctions de fonctions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	MCN::Math::CFunction h;
    	h.SetFunction("B(x) = x^5 + 3 * x ^ 4 + 2");  // une exception est lancé en cas d'erreur
    
    	MCN::Math::CFunction f;
    	f.SetFunction("f(t) = A * sin ( W * t + B(t) )");
    
    	cout << "B(x) = x^5 + 3 * x ^ 4 + 2" << endl;
    	cout << "f(t) = A * sin ( W * t + B(t) )" << endl << endl;
    
    	cout << "B(2.5) = " << h(2.5) << endl;
    	cout << "f(0) = " << f(0.0) << endl;
    	cout << "f(2.5) = " << f(2.5) << endl;
    	cout << "f(10) = " << f(10.0) << endl << endl;
    Les foncteurs h et f s'identifient aux fonctions B(x) et f(t) respectivement.
    Les expressions B(x) et f(t) s'incrivent également dans la tables des expressions globales.
    Puisque f(t) dépend de A, de W et de B(x) ces dernières expressions sont supposées déjà inscrites dans la table des expressions globales avant f(t).

    Remarque : Un objet CFunction ou CVariable a son expression inscrite dans la table tant que cet objet existe. En d'autres termes la durée de vie d'une expression soit variable ou fonction dans la table des expressions globales est lié à la durée de vie de l'objet CVariable ou CFunction respectivement auquel il est attaché.

    Je n'ai fais que respecté la logique de la durée de vie d'un objet C++ dans sa portée.
    Lorsque CFunction ou CVariable passe dans leur destructeur. Leurs expressions sont désincrites de la table des expressions globales.

    La suite finale dans _tmain() est l'exemple d'utilisation d'une fonction à plusieur variables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    MCN::Math::CFunction F2;
    	F2.SetFunction("Parabole3D(x, y) = x^2 + y^2");  // une exception est lancé en cas d'erreur
     
    	cout << "Parabole3D(x, y) = x^2 + y^2" << endl << endl;
    	cout << "Parabole3D(1, 2) = " << F2(1.0, 2.0) << endl;
    	cout << "Parabole3D(3, -4) = " << F2(3.0, -4.0) << endl;
    	cout << "Parabole3D(2.5, 2) = " << F2(2.5, 2.0) << endl << endl;
     
    	cout << "Tapez sur touche pour terminer" << endl;
    	_getch();
     
    	return 0;
    }
    Le foncteur F2 s'identifie à la fonction Parabole3D(x, y) qui s'inscrit dans la table des expressions globales.

    La sortie du programme console donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    P(x) = x^5 + 3 * x ^ 4 + 2
     
    P(1) = 6
    P(3.2) = 652.117
    P(-5) = -1248
     
     
    A = sqrt(pi / 2)  + 1
    W = 2 * pi
     
    A = 2.25331
    W = 6.28319
    B(x) = x^5 + 3 * x ^ 4 + 2
    f(t) = A * sin ( W * t + B(t) )
     
    B(2.5) = 216.844
    f(0) = 2.04893
    f(2.5) = 0.166272
    f(10) = 0.547863
     
    Parabole3D(x, y) = x^2 + y^2
     
    Parabole3D(1, 2) = 5
    Parabole3D(3, -4) = 25
    Parabole3D(2.5, 2) = 10.25
     
    Tapez sur touche pour terminer
    Je vous envoie le projet Mcn.Math avec de bon settings et le projet de test


  4. #4
    Membre éprouvé
    Avatar de Gabrielly
    Inscrit en
    Juin 2004
    Messages
    722
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 722
    Points : 1 128
    Points
    1 128
    Par défaut
    Voici le solver d'équations
    Fichiers attachés Fichiers attachés

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Lazarus] Interpréteur d'expression mathématique
    Par Rawly dans le forum Lazarus
    Réponses: 0
    Dernier message: 16/04/2012, 11h43
  2. Défi N°2 : Réalisation d'un interpréteur d'expression mathématiques
    Par millie dans le forum Défis langages fonctionnels
    Réponses: 22
    Dernier message: 13/01/2011, 14h15
  3. Réponses: 2
    Dernier message: 07/01/2011, 11h29
  4. [Source] Evaluer une expression algébrique
    Par Delbeke dans le forum Vos contributions VB6
    Réponses: 6
    Dernier message: 22/08/2006, 11h52
  5. Analyser une expression mathématique
    Par Amokrane dans le forum C++
    Réponses: 5
    Dernier message: 06/01/2006, 13h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo