Question 141

Comment évaluer la valeur d'une expression mathématique ?

Le programmeur est parfois confronté au problème consistant à devoir évaluer une expression mathématique, simple ou complexe. Visual Basic ne dispose pas d'une instruction ou fonction permettant de traiter directement cette problématique. Cependant, il y a plusieurs solutions envisageables pour résoudre ce problème:

  • Utilisation du ScriptControl
  • Utilisation de l'API EbExecuteLine
  • Utilisation du moteur Jet
  • Utilisation d'une librairie toute faite
  • Ecriture de sa propre fonction d'évaluation
Chacune de ces solutions présente des avantages et des inconvénients, exposés dans la suite de cet article.

Le Script Control

A partir de Windows 98 et Windows NT, vous pouvez employer le Script Control et sa méthode Eval qui permet d'évaluer une expression mathématique. La première chose à faire sera donc d'ajouter une référence à celui-ci. Pour ce faire, cliquez sur le menu "Projet/Références..." Et dans la liste des références disponibles, sélectionnez "Microsoft ScriptControl 1.0."

Vous pouvez ensuite essayer cet exemple :

Option Explicit

Private Sub Form_Load()

    Dim sc As ScriptControl
    Set sc = New ScriptControl

    sc.Language = "VBScript"
    MsgBox "(4 * 9) + 4 = " & sc.Eval("(4 * 9) + 4")

    Set sc = Nothing

End Sub

A noter qu'il est aussi possible d'utiliser un autre script engine que VBScript, par exemple JScript.
Pour ces différents scripting engines, une documentation très détaillée est disponible ici :

Le Script Control permet aussi de fournir de nouveaux objets, sous forme de classes. En fait, le Script Control est un contrôle extrêmement puissant, dont les possibilités dépassent de très loin ce qu'il est possible de couvrir ici.
Le lecteur intéressé pourra se référer utilement à cet article qui fournit des explications détaillées ainsi que des exemples concrets de ce qu'il est possible de faire avec ce contrôle : Exploring the Microsoft Script Control

A noter que ce composant doit être redistribué avec votre application. Le redistribuable est disponible ici : Download details : Windows Script Control

API EbExecuteLine

Une autre solution consiste à employer l'API "EbExecuteLine", interne à Visual Basic. Cette fonction permet d'exécuter n'importe quelle ligne de code et donc, en particulier, d'évaluer une expression numérique. Seulement cette fonction n'est ni documentée, ni supportée par Microsoft et ne fonctionne qu'en mode débuggage. Ajoutez à cela que le fichier VB6.dll n'est PAS REDISTRIBUABLE. Vous ne pourrez donc utiliser cette technique que sur un poste possédant Visual Basic. Et ce, à vos risques et périls.

Voici un exemple d'utilisation de cette fonction :

Option Explicit

Public Number1 As Long
Public Number2 As Long

Private Declare Function EbExecuteLine _
    Lib "vba6.dll" _
    ( _
        ByVal pStringToExec As Long, _
        ByVal Foo1 As Long, _
        ByVal Foo2 As Long, _
        ByVal fCheckOnly As Long _
    ) As Long

Public Function Execute(CodeLine As String, Optional CheckOnly As Boolean = False)

    Execute = (EbExecuteLine(StrPtr(CodeLine), 0&, 0&, Abs(CheckOnly)) = 0)

End Function

Public Sub Main()

    ' Exécute : MsgBox "Ceci est un test"
    Call Execute("MsgBox ""Ceci est un test""")
    ' Exécute : Number1 = 1024
    Call Execute("Number" & 1 & " = 1024")
    ' Exécute : Number2 = Number1 + 1024
    Call Execute("Number" & 2 & " = Number" & 1 & " + 1024")
    ' Affiche la somme de Number1 et Number2 (soit 3072)
    MsgBox Number1 + Number2

End Sub

Note : les variables Number1 et Number2 doivent être déclarées en Global afin de les rendre accessibles par l'API.
Ce code n'est valable que pour Visual Basic 6.0. Si vous employer la version 5.0, vous devrez remplacer la déclaration de l'API par :

Private Declare Function EbExecuteLine _
    Lib "vba5.dll" _
    (ByVal pStringToExec As Long, _
    ByVal Foo1 As Long, _
    ByVal Foo2 As Long, _
    ByVal fCheckOnly As Long) As Long

Enfin, le paramètre "CheckOnly" permet de spécifier s'il faut exécuter la ligne la ligne de code ou simplement vérifier si celle-ci est correcte.

Utilisation du moteur Jet

Cette solution est originale tout en étant extrêmement puissante et très simple à mettre en oeuvre. Elle utilise le fait que le moteur Jet (le moteur de base de données d'Access) permet en lui même d'évaluer des expressions mathématiques dans un simple SELECT.
Ainsi, une requête telle que : SELECT 3*4+2 FROM TABLE; retourne 14 en tant que résultat.
Pour faire fonctionner ceci, il faut simplement :
  • Ajouter au projet une référence à Microsoft DAO 3.51 ou supérieur
  • Créer un petit fichier texte, à mettre dans le répertoire de l'application
Le fichier texte pourra être de la forme :
"Pi";"e"
3,1415926535897932384626433832795;2,71828182845905

On peut mettre autant de valeurs que nécessaires, ces valeurs devenant accessibles depuis l'évaluateur.
Le code ensuite est extrêmement simple :

Public Function MyEval(expression As String) As Variant
   
    Dim db As Database
    Dim rs As Recordset

    Set db = OpenDatabase(App.Path, False, True, "Text;")
    Set rs = db.OpenRecordset("SELECT " & expression & " FROM data.dat;")
    MyEval = rs(0)
    rs.Close
    db.Close
    Set rs = Nothing
    Set db = Nothing
   
End Function

Pour appeler cette fonction, il suffit de faire (par exemple) :

Private Sub Command1_Click()
   
    Dim result As Variant

    result = MyEval(Text1.Text)
    MsgBox result
   
End Sub

On peut maintenant évaluer des expressions telles que:
"3*4+2", "12*Cos(Pi/2)", etc.

A noter que vous devez alors redistribuer le moteur Jet avec votre application. Toutes les informations utiles ainsi que les fichiers à télécharger sont disponibles ici : Obtenir le dernier Service Pack pour Microsoft jet
Note : Si vous utilisez une référence à Microsoft DAO 3.51, l'assistant d'empaquetage et déploiement incluera automatiquemen tous les fichiers nécessaires. Ne pas oublier d'inclure le Driver "text".

Utiliser une solution existante

Si aucune de ces solutions ne vous convient, vous pouvez toujours essayer de chercher sur Internet une libraire "prête à l'emploi" répondant à votre problème.
Voici quelques exemples de solutions existantes :
A noter que ces solutions sont peu coûteuses (quelques dizaines de dollars US). Certaines sont même gratuites pour une utilisation personnelle.
Vous trouverez depuis cette page de très nombreux liens présentant des solutions existantes : http://www.programurl.com/software/expression-parser.htm

Créer sa propre fonction d'évaluation

Une autre possibilité consiste à créer votre propre fonction d'évaluation. Ce n'est pas si compliqué et constitue en soi un exercice amusant. Qui plus est, vous pourrez alors intégrer à votre évaluateur les spécificités dont vous auriez besoin.
Un autre intérêt d'une solution "propriétaire" est que celle ci vous dispense de prendre en compte des considérations de redistribution de composants tiers. Le dernier avantage (par rapport à une solution "toute faite") est qu'en cas de soucis, vous êtes l'auteur du code et avez donc toutes les facilités pour debugger votre interpréteur.

La réalisation d'un tel interpréteur dépasse le cadre de cet article, mais un article détaillant la création d'un tel évaluateur est en préparation. Cet article sera disponible lors des prochaines mise à jour, dans la section "Algorithmique".

Date de publication : 19 novembre 2006
Dernière modification : 19 novembre 2006
Rubriques : Math
Mots-clés : évaluation,interpréteur,expression,eval,script