Analyse syntaxique de fonctions mathématiques(new!!)

Contenu du snippet

Voici un nouvel algorithme d'analyse de fonctions mathématiques qui est mieu que le précédent que j'ai publié.
Celui-ci respecte totalement les règles de calculs(i.e. les priorités de calcul) et permet, entre autre d'introduire une variable dans l'équation ou encore d'écrire directement "log x" au lieu de "log(x)", bien qu'il reconnaisse les 2 formes.
Le code qui suit est à insérer dans un module.

Source / Exemple :


Option Explicit
Private Type SYNTAX
    T() As Byte
    P As Integer
End Type
Private Const Fonctions As String = "cos240sin241tan242atn243log244exp245"
Private sntA As SYNTAX
Private Function Conversion(ByRef ch As String, Optional VAR As Double) As Boolean
    ch = LCase(ch)
    
    Dim i As Integer, k As Integer, lng As Long, str As String, f As Integer
    lng = Len(ch)
    ReDim sntA.T(1 To 32767)
    For i = 1 To lng
        k = k + 1
        str = Mid(ch, i, 1)
        If str = " " Then   'on ne compte pas les espaces
            k = k - 1
        ElseIf Not (str >= "a" And str <= "z") Then
            sntA.T(k) = Asc(str)
        ElseIf str = "x" Then   'LA variable
            sntA.T(k) = 255
        Else
            f = InStr(Fonctions, Mid(ch, i, 3))
            '--Erreurs
            If f <= 0 Then sntA.P = i: ReDim sntA.T(0 To 0): Exit Function
            '---------
            sntA.T(k) = Val(Mid(Fonctions, f + 3, 3))
            i = i + 2
        End If
    Next
    Conversion = True
    ReDim Preserve sntA.T(1 To k + 1)
    sntA.T(k + 1) = 0
    sntA.P = 1
End Function

Private Function Nmbre(ByVal i As Integer, VAR As Double) As Double
    If sntA.T(i) <= 245 And sntA.T(i) >= 240 Then   '"[fonction]"
        Select Case sntA.T(i)
            Case 240    '"cos"
                sntA.P = i + 1
                Nmbre = Cos(Nmbre(sntA.P, VAR))
                i = sntA.P
            Case 241    '"sin"
                sntA.P = i + 1
                Nmbre = Sin(Nmbre(sntA.P, VAR))
                i = sntA.P
            Case 242    '"tan"
                sntA.P = i + 1
                Nmbre = Tan(Nmbre(sntA.P, VAR))
                i = sntA.P
            Case 243    '"atn"
                sntA.P = i + 1
                Nmbre = Atn(Nmbre(sntA.P, VAR))
                i = sntA.P
            Case 244    '"log"
                sntA.P = i + 1
                Nmbre = Log(Nmbre(sntA.P, VAR))
                i = sntA.P
            Case 245    '"exp"
                sntA.P = i + 1
                Nmbre = Exp(Nmbre(sntA.P, VAR))
                i = sntA.P
        End Select
    End If
    
    If sntA.T(i) = 255 Then '"x"
        Nmbre = VAR
        sntA.P = i + 1
        Exit Function
    End If
    
    If sntA.T(i) = 40 Then  '"("
        sntA.P = i + 1
        Nmbre = Valeur(sntA.P, VAR)
        i = sntA.P
    End If
    
    While sntA.T(i) <= 57 And sntA.T(i) >= 48 '"0..9"
         Nmbre = Nmbre * 10 + sntA.T(i) - 48
         i = i + 1
    Wend
    
    If sntA.T(i) = 46 Then  '"."
        Dim j As Integer
        i = i + 1
        While sntA.T(i) <= 57 And sntA.T(i) >= 48 '"0..9"
            j = j + 1
            Nmbre = Nmbre + (sntA.T(i) - 48) / 10 ^ j
            i = i + 1
        Wend
    End If
    If sntA.T(i) = 94 Then  '"^"
        sntA.P = i + 1
        Nmbre = Nmbre ^ Nmbre(sntA.P, VAR)
        i = sntA.P
    End If
    sntA.P = i
End Function

Private Function Term(ByVal i As Integer, VAR As Double) As Double
    Term = Nmbre(i, VAR)
    i = sntA.P
    Do
    Select Case sntA.T(i)
        Case 42 '"*"
            sntA.P = i + 1
            Term = Term * Nmbre(sntA.P, VAR)
            i = sntA.P
        Case 47 '"/"
            sntA.P = i + 1
            Term = Term / Nmbre(sntA.P, VAR)
            i = sntA.P
        Case Else
            Exit Do
    End Select
    Loop
End Function

Private Function Valeur(ByVal i As Integer, VAR As Double) As Double
    Valeur = Term(i, VAR)
    i = sntA.P
    Do
        Select Case sntA.T(i)
            Case 43 '"+"
                sntA.P = i + 1
                Valeur = Valeur + Term(sntA.P, VAR)
                i = sntA.P
            Case 45 '"-"
                sntA.P = i + 1
                Valeur = Valeur - Term(sntA.P, VAR)
                i = sntA.P
            Case 41 '")"
                sntA.P = i + 1
                Exit Function
            Case 0
                Exit Function
        End Select
    Loop
End Function

Public Function Analyse(ByRef Expression As String, Optional ByRef VAR As Double) As Double
    Dim bln As Boolean
    bln = Conversion(Expression)
    If bln Then
        Analyse = Valeur(1, VAR)
    Else
        MsgBox "Syntaxe incorrecte <caractère" & sntA.P & ">.", vbExclamation Or vbOKOnly, "Analyse Syntaxique -- ERREUR"
    End If
End Function

Conclusion :


Voici quelques notes qui pourront aider à comprendre le code

40 (
41 )
42 *
43 +
45 -
47 /
94 ^
46 .
48..57 0..9
240 cos
241 sin
242 tan
243 atn
244 log
245 exp

Hiérarchie syntaxique :
Valeur>Term>Nmbre

exemple:
3*2-5*log(10)+2^3/5 = Valeur

1°)
3*2 = Term1
5*log 10= Term2
2^3/5 = Term3
on a donc Term1-Term2+Term3

2°)
Term1:
3 = Nmbre11
2 = Nmbre12
Term2:
5 = Nmbre21
log(10) = Nmbre22
Term3:
2^3 = Nmbre31
5 = Nmbre32
on a donc (Nmbre11*Nmbre12)-(Nmbre21*Nmbre22)+(Nmbre31/Nmbre32)
Term1 - Term2 + Term3

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.