Vérificateur + Evaluateur d'expressions mathématique

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Vérificateur + Evaluateur d'expressions mathématique

Message par Shadow »

Voila je met ça ici:

L'IA à créer l'Evaluateur et moi le Vérificateur.

Code : Tout sélectionner

; Fonction pour valider une chaîne représentant une expression mathématique.
; Créer par Shadow (Dieppedalle David) le 10/12/2024.
Procedure.s CheckMathExpression(Expression$)
  
  ; Si l'expression est vide ou ne contient que des espaces.
  If Expression$ = "" Or ReplaceString(Expression$, Chr(32), "") = ""
    ProcedureReturn "Erreur: L'expression est vide."
    
  Else
    
    ; Initialisation des variables nécessaires à la validation.
    ParenthesesCount.i = 0 ; Compteur pour suivre l'équilibre des parenthèses ouvrantes et fermantes.
    LastChar.s = ""        ; Précédent caractère significatif analysé.
    PositionLastChar.i = 0 ; Position du précédent caractère significatif.
    CurrentChar.s = ""     ; Caractère actuellement analysé.
    NombreVirgule.b = #False ; Indicateur de la gestion des virgules dans un nombre décimal.
    
    ExpressionLength.i = Len(Expression$) ; Longueur totale de l'expression.
    
    ; Parcourir chaque caractère de l'expression.
    For IndexExpression.i = 1 To ExpressionLength.i
      
      ; Extraire le caractère actuel.
      CurrentChar.s = Mid(Expression$, IndexExpression.i, 1)
      
      ; Vérifier que le caractère est autorisé.
      If Not FindString("0123456789+-*/(), ", CurrentChar.s)
        ProcedureReturn "Erreur: Caractère non autorisé '" + CurrentChar.s + "' à la position " + Str(IndexExpression.i) + "."
      EndIf
      
      ; Gestion des parenthèses ouvrantes.
      If CurrentChar.s = "("
        
        ; Vérification: une parenthèse ouvrante ne peut pas suivre une virgule.
        If LastChar.s = ","
          ProcedureReturn "Erreur: Chiffre manquant après la Virgule à la position " + Str(PositionLastChar.i) + ": " + LastChar.s
        EndIf
        
        ParenthesesCount.i + 1 ; Incrémenter le compteur de parenthèses ouvrantes.
        
        ; Réinitialiser le suivi des virgules.
        If NombreVirgule.b = #True
          NombreVirgule.b = #False
        EndIf
        
        ; Gestion des parenthèses fermantes.
      ElseIf CurrentChar.s = ")"
        
        ; Vérification: parenthèse fermante inattendue.
        If ParenthesesCount.i <= 0
          ProcedureReturn "Erreur: Parenthèse fermante inattendue à la position " + Str(IndexExpression.i) + "."
        Else
          
          ParenthesesCount.i -1 ; Décrémenter le compteur de parenthèses.
          
          ; Vérifications contextuelles pour la parenthèse fermante.
          If LastChar.s = "+" Or LastChar.s = "-" Or LastChar.s = "*" Or LastChar.s = "/"
            ProcedureReturn "Erreur: Opérateur invalide à la position " + Str(PositionLastChar.i) + ": " + LastChar.s
          ElseIf LastChar.s = ","
            ProcedureReturn "Erreur: Chiffre manquant après la Virgule à la position " + Str(PositionLastChar.i) + "."
          ElseIf LastChar.s = "("
            ProcedureReturn "Erreur: Parenthèse vide à la position " + Str(IndexExpression.i) + "."
          EndIf
        EndIf
        
        ; Réinitialiser le suivi des virgules.
        If NombreVirgule.b = #True
          NombreVirgule.b = #False
        EndIf
        
        ; Gestion des chiffres
      ElseIf (CurrentChar.s >= "0" And CurrentChar.s <= "9")
        
        ; Vérification: un chiffre ne peut pas suivre une parenthèse fermante.
        If LastChar.s = ")"
          ProcedureReturn "Erreur: Parenthèse fermante invalide à la position " + Str(PositionLastChar.i)
        EndIf
        
        ; Gestion des opérateurs (+, -, *, /)
      ElseIf CurrentChar.s = "+" Or CurrentChar.s = "-" Or CurrentChar.s = "*" Or CurrentChar.s = "/"
        
        ; Réinitialiser le suivi des virgules après un opérateur.
        If NombreVirgule.b = #True
          NombreVirgule.b = #False
        EndIf
        
        ; Vérification: un opérateur ne peut pas suivre un autre opérateur ou être isolé, sauf cas particulié pour l'oppérateur "-".
        ; Exemples qui fonctionne: 45 - -12 | 21 + -36 |  67 * -91 | 37 / -29.
        
        ; Si le précédent caractère n'est pas un chiffre, sinon c'est bon.
        If (LastChar.s < "0" Or LastChar.s > "9")
          Select CurrentChar.s
            Case "+", "*", "/" ; Le caracère actuel est un Oppérateur autre que "-".
              If LastChar.s = "+" Or LastChar.s = "-" Or LastChar.s = "*" Or LastChar.s = "/" Or LastChar.s = "(" Or LastChar.s = "" ; Si le précédent caractère n'est pas un Oppérateur ni "(", ni rien.
                ProcedureReturn "Erreur: Opérateur invalide à la position " + Str(IndexExpression.i) + ": " + CurrentChar.s
              EndIf
            Case "-" ; Le caracère actuel est "-", cas spécial ici.
              If LastChar.s = ","
                ProcedureReturn "Erreur: Chiffre manquant après la Virgule à la position " + Str(PositionLastChar.i) + "."
              EndIf
            Default
          EndSelect
          If LastChar.s = "," ; Si le précédent caractère est une virgule.
            ProcedureReturn "Erreur: Chiffre manquant après la Virgule à la position " + Str(PositionLastChar.i) + "."
          EndIf
        EndIf
        
        ; Gestion des virgules.
      ElseIf CurrentChar.s = ","
        
        ; Vérification: une virgule ne peut pas suivre une autre virgule.
        If LastChar.s = ","
          ProcedureReturn "Erreur: Chiffre manquant après la Virgule à la position " + Str(PositionLastChar.i) + "."
          ; Vérification: une virgule doit suivre un chiffre.
        ElseIf (LastChar.s < "0" Or LastChar.s > "9")
          ProcedureReturn "Erreur: Virgule invalide à la position " + Str(IndexExpression.i) + "."
        EndIf
        
        ; Mettre à jour le suivi des virgules.
        If NombreVirgule.b = #False
          NombreVirgule.b = #True
        Else
          ProcedureReturn "Erreur: Virgule invalide à la position " + Str(IndexExpression.i) + "."
        EndIf
        
        ; Ignorer les espaces.
      ElseIf CurrentChar.s = " "
        Continue
      EndIf
      
      ; Mise à jour des informations sur le précédent caractère significatif.
      If CurrentChar.s <> Chr(32)
        LastChar.s = CurrentChar.s
        PositionLastChar.i = IndexExpression.i
      EndIf
      
    Next
    
    ; Vérification finale après la fin de la boucle.
    If LastChar.s = "+" Or LastChar.s = "-" Or LastChar.s = "*" Or LastChar.s = "/"
      ProcedureReturn "Erreur: Opérateur invalide à la position " + Str(PositionLastChar.i) + ": " + LastChar.s
    ElseIf LastChar.s = "("
      ProcedureReturn "Erreur: Parenthèse ouvrante invalide à la position " + Str(PositionLastChar.i) + "."
    ElseIf ((LastChar.s < "0" Or LastChar.s > "9") And LastChar.s <> ")")
      ProcedureReturn "Erreur: Caractère invalide à la position " + Str(PositionLastChar.i) + ": " + LastChar.s
    EndIf
    
    ; Vérification de l'équilibre des parenthèses.
    If ParenthesesCount.i <> 0
      ProcedureReturn "Erreur: Parenthèse fermante manquante à la position " + Str(IndexExpression.i) + "."
    EndIf
    
  EndIf
  
  ; Si aucune erreur n'a été détectée, retourner "Pas d'erreur".
  ProcedureReturn "Pas d'erreur."
  
EndProcedure

; Code Créé par ChatGpt le 08/12/2024.
; ---

; Fonction pour remplacer les virgules par des points dans une chaîne
Procedure.s ReplaceCommaWithDot(Expression$)
  ProcedureReturn ReplaceString(Expression$, ",", ".")
EndProcedure

; Fonction pour déterminer la priorité des opérateurs
Procedure.i GetOperatorPrecedence(op$)
  Select op$
    Case "+", "-": ProcedureReturn 1
    Case "*", "/": ProcedureReturn 2
    Default: ProcedureReturn 0
  EndSelect
EndProcedure

; Fonction pour appliquer un opérateur à deux valeurs
Procedure.d ApplyOperator(a.d, b.d, op$)
  Select op$
    Case "+": ProcedureReturn a + b
    Case "-": ProcedureReturn a - b
    Case "*": ProcedureReturn a * b
    Case "/": ProcedureReturn a / b
  EndSelect
EndProcedure

; Fonction pour analyser et évaluer une expression mathématique
Procedure.d EvaluateExpression(Expression$)
  Protected operators$ = "+-*/()"
  Protected NewList stackOperators.s()
  Protected NewList stackValues.d()
  Protected tempNumber.s
  Protected i.i, result.d
  
  ; Vérifie avant l'expression pour voir si elle est correcte.
  If CheckMathExpression(Expression$) = "Pas d'erreur."
    
    ; Remplacer les virgules par des points
    Expression$ = ReplaceCommaWithDot(Expression$)
    
    ; Parcourir chaque caractère de l'expression
    For i = 1 To Len(Expression$)
      Define char.s = Mid(Expression$, i, 1)
      
      If FindString("0123456789.", char)
        tempNumber + char
      ElseIf FindString(operators$, char)
        If tempNumber <> ""
          AddElement(stackValues())
          stackValues() = ValD(tempNumber)
          tempNumber = ""
        EndIf
        
        If char = "(" 
          AddElement(stackOperators())
          stackOperators() = char
        ElseIf char = ")"
          While ListSize(stackOperators()) > 0 And LastElement(stackOperators()) And stackOperators() <> "("
            Define op.s = stackOperators()
            DeleteElement(stackOperators())
            
            Define b.d = stackValues()
            DeleteElement(stackValues())
            Define a.d = stackValues()
            DeleteElement(stackValues())
            
            result = ApplyOperator(a, b, op)
            
            AddElement(stackValues())
            stackValues() = result
          Wend
          DeleteElement(stackOperators())
        Else
          While ListSize(stackOperators()) > 0 And LastElement(stackOperators()) And GetOperatorPrecedence(stackOperators()) >= GetOperatorPrecedence(char)
            Define op.s = stackOperators()
            DeleteElement(stackOperators())
            
            Define b.d = stackValues()
            DeleteElement(stackValues())
            Define a.d = stackValues()
            DeleteElement(stackValues())
            
            result = ApplyOperator(a, b, op)
            
            AddElement(stackValues())
            stackValues() = result
          Wend
          AddElement(stackOperators())
          stackOperators() = char
        EndIf
      EndIf
    Next
    
    If tempNumber <> ""
      AddElement(stackValues())
      stackValues() = ValD(tempNumber)
    EndIf
    
    While ListSize(stackOperators()) > 0
      Define op.s = stackOperators()
      DeleteElement(stackOperators())
      
      Define b.d = stackValues()
      DeleteElement(stackValues())
      Define a.d = stackValues()
      DeleteElement(stackValues())
      
      result = ApplyOperator(a, b, op)
      
      AddElement(stackValues())
      stackValues() = result
    Wend
    
    ProcedureReturn stackValues()
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; ---

; Exemple 1
Expression$ = "(2+3)*4"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(2+3)*4")) ; Résultat attendu : 20
; Étapes :
; (2+3) = 5
; 5*4 = 20
Debug "Calcule direct: " + StrD((2+3)*4) ; Résultat attendu : 20
Debug "----"

; Exemple 2
Expression$ = "2*(3+(4*5))"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("2*(3+(4*5))")) ; Résultat attendu : 46
; Étapes :
; (4*5) = 20
; (3+20) = 23
; 2*23 = 46
Debug "Calcule direct: " + StrD(2*(3+(4*5))) ; Résultat attendu : 46
Debug "----"

; Exemple 3
Expression$ = "((2+3)*4)/2"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("((2+3)*4)/2")) ; Résultat attendu : 10
; Étapes :
; (2+3) = 5
; (5*4) = 20
; 20/2 = 10
Debug "Calcule direct: " + StrD(((2+3)*4)/2) ; Résultat attendu : 10
Debug "----"

; Exemple 4
Expression$ = "29+(83*(47-82))/29"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("29+(83*(47-82))/29")) ; Résultat attendu : -71.1724137931
; Étapes :
; (47-82) = -35
; (83*-35) = -2905
; -2905/29 = -100.1724137931
; 29+(-100.1724137931) = -71.1724137931
Debug "Calcule direct: " + StrD(29+(83*(47-82))/29) ; Résultat attendu : -71.1724137931
Debug "----"

; Exemple 5
Expression$ = "2+3"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("2+3")) ; Résultat attendu : 5
; Étapes :
; 2+3 = 5
Debug "Calcule direct: " + StrD(2+3) ; Résultat attendu : 5
Debug "----"

; Exemple 6
Expression$ = "2+3*4"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("2+3*4")) ; Résultat attendu : 14
; Étapes :
; (3*4) = 12
; 2+12 = 14
Debug "Calcule direct: " + StrD(2+3*4) ; Résultat attendu : 14
Debug "----"

; Exemple 7
Expression$ = "10/2+5"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("10/2+5")) ; Résultat attendu : 10
; Étapes :
; (10/2) = 5
; 5+5 = 10
Debug "Calcule direct: " + StrD(10/2+5) ; Résultat attendu : 10
Debug "----"

; Exemple 8
Expression$ = "(2+3)*(4+5)"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(2+3)*(4+5)")) ; Résultat attendu : 45
; Étapes :
; (2+3) = 5
; (4+5) = 9
; 5*9 = 45
Debug "Calcule direct: " + StrD((2+3)*(4+5)) ; Résultat attendu : 45
Debug "----"

; Exemple 9
Expression$ = "(10+5)/(2+3)"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(10+5)/(2+3)")) ; Résultat attendu : 3
; Étapes :
; (10+5) = 15
; (2+3) = 5
; 15/5 = 3
Debug "Calcule direct: " + StrD((10+5)/(2+3)) ; Résultat attendu : 3
Debug "----"

; Exemple 10
Expression$ = "((2+3)*4)/(2+3)"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("((2+3)*4)/(2+3)")) ; Résultat attendu : 4
; Étapes :
; (2+3) = 5
; (5*4) = 20
; 20/5 = 4
Debug "Calcule direct: " + StrD(((2+3)*4)/(2+3)) ; Résultat attendu : 4
Debug "----"

; Exemple 11
Expression$ = "(5-10)*(3+7)"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(5-10)*(3+7)")) ; Résultat attendu : -50
; Étapes :
; (5-10) = -5
; (3+7) = 10
; -5*10 = -50
Debug "Calcule direct: " + StrD((5-10)*(3+7)) ; Résultat attendu : -50
Debug "----"

; Exemple 12
Expression$ = "(((8+2)*3)-10)/(5+(7-3))"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(((8+2)*3)-10)/(5+(7-3))")) ; Résultat attendu : 2.2222222222
; Étapes :
; (8+2) = 10
; (10*3) = 30
; (30-10) = 20
; (7-3) = 4
; (5+4) = 9
; 20/9 = 2.2222222222
Debug "Calcule direct: " + StrD((((8+2)*3)-10)/(5+(7-3))) ; Résultat attendu : 2.2222222222
Debug "----"

; Exemple 13
Expression$ = "496587,125478963 * 65123,397845412"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("496587,125478963 * 65123,397845412")) ; Résultat attendu : 32339440937.4760398865
; Étapes :
; Remplacement des virgules par des points
; (496587.125478963 * 65123.397845412) = 32339440937.4760398865
Debug "Calcule direct: " + StrD(496587.125478963 * 65123.397845412) ; Résultat attendu : 32339440937.4760398865
Debug "----"

; Exemple 14
Expression$ = "1,5 + 2,75"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("1,5 + 2,75")) ; Résultat attendu : 4.25
; Étapes :
; Remplacement des virgules par des points
; (1.5 + 2.75) = 4.25
Debug "Calcule direct: " + StrD(1.5 + 2.75) ; Résultat attendu : 4.25
Debug "----"

; Exemple 15
Expression$ = "10,0 / 3,2"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("10,0 / 3,2")) ; Résultat attendu : 3.125
; Étapes :
; Remplacement des virgules par des points
; (10.0 / 3.2) = 3.125
Debug "Calcule direct: " + StrD(10.0 / 3.2) ; Résultat attendu : 3.125
Debug "----"

; Exemple 16
Expression$ = "(10,5 + 2,25) * 4,1"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(10,5 + 2,25) * 4,1")) ; Résultat attendu : 52.275
; Étapes :
; Remplacement des virgules par des points
; (10.5 + 2.25) = 12.75
; 12.75 * 4.1 = 52.275
Debug "Calcule direct: " + StrD((10.5 + 2.25) * 4.1) ; Résultat attendu : 52.275
Debug "----"

; Exemple 17
Expression$ = "29,5 + (83,75 * (47,5 - 82,25)) / 29,75"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("29,5 + (83,75 * (47,5 - 82,25)) / 29,75")) ; Résultat attendu : -68.3256302521
; Étapes :
; Remplacement des virgules par des points
; (47.5 - 82.25) = -34.75
; (83.75 * -34.75) = -2909.0625
; -2909.0625 / 29.75 = -97.8256302521
; 29.5 + (-97.8256302521) = -68.3256302521
Debug "Calcule direct: " + StrD(29.5 + (83.75 * (47.5 - 82.25)) / 29.75) ; Résultat attendu : -68.3256302521
Debug "----"

; Exemple 18
Expression$ = "(((200,5 + (50,25 * (6,5 - 4,25))) / (3,75 + 2,5)) * ((10,75 + 5,5) / (7,25 - 3,5)))"
Debug "Expression: " + Expression$
Debug "Vérification de l'expression: " + CheckMathExpression(Expression$)
Debug "Calcule évalué: " + StrD(EvaluateExpression("(((200,5 + (50,25 * (6,5 - 4,25))) / (3,75 + 2,5)) * ((10,75 + 5,5) / (7,25 - 3,5)))")) ; Résultat attendu : 217.4033333333
; Étapes :
; Remplacement des virgules par des points
; (6.5 - 4.25) = 2.25
; (50.25 * 2.25) = 113.0625
; (200.5 + 113.0625) = 313.5625
; (3.75 + 2.5) = 6.25
; (313.5625 / 6.25) = 50.169
; (10.75 + 5.5) = 16.25
; (7.25 - 3.5) = 3.75
; (16.25 / 3.75) = 4.3333333333
; (50.169 * 4.3333333333) = 217.4033333333
Debug "Calcule direct: " + StrD((((200.5 + (50.25 * (6.5 - 4.25))) / (3.75 + 2.5)) * ((10.75 + 5.5) / (7.25 - 3.5)))) ; Résultat attendu : 217.4033333333
Debug "----"
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.