XL 2019 Problème calcul % sur calculatrice

  • Initiateur de la discussion Initiateur de la discussion Nathe
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Nathe

XLDnaute Junior
Bonjour à toutes et tous,

Je suis en train d'essayer de monter un projet calculatrice sur excel mais je peine sur l'adaptation du calcul du pourcentage,
Si une personne saurai comment effectué le code qui irai bien.

Merci à tous
Nathe

Animation.gif
 

Pièces jointes

Bon alors
Bonjour @Nathe , @jurassic pork,@rheeem,etc...
j'ai repris le truc 5 minutes afin de réduire le code de réduction (développement)de l'operation avec des parenthèses en veux tu en voilà
c'est devenu un code tout simple
Pour afficher ce contenu, nous aurons besoin de votre consentement pour définir des cookies tiers.
Pour plus d'informations, consultez notre page sur les cookies.
je livre le userform d'essai
je pense que c'est une bonne base pour pouvoir travailler après sur les règles de priorité(unfois qu'il n'y a plus ces parenthèses

patrick
 

Pièces jointes

Bonjour,
Merci pour votre persévérance, toutefois j'ai essayé à plusieurs reprise, votre est presque juste, mais merci pour votre travail.

L'affichage de l'ordre d’évaluation de cette expression n'est pas correcte, c'est l'expression (45x2.8) qui doit être evaluer en premier ,
Regarde dans code que j'ai fourni dans un poste précédent
En plus le code calcule correctement le % :
20+10+30%
Donc affiche 39
 
Dernière édition:
Hello,
je suis en train d'étudier Lex yacc qui sont des outils utiles si vous voulez créer un compilateur, un transpiler ou si vous voulez simplement interpréter un langage formel. On part de deux fichiers de description :
1 fichier de description des jetons (.lex) qui sont spécifiés par des expressions régulières :
exemple (partie) :
C#:
Eol             (\r\n?|\n)
NotWh           [^ \t\r\n]
Space           [ \t]
Digit   [0-9]
Integer {Digit}+
Ndigit  (\-)?{Digit}+
Float      {Digit}+(\.){Digit}+
Exponent ({Digit}+|{Float}+)(E|e){Ndigit}+
OpPlus            \+
OpMinus            \-
OpMult            \*
OpDiv            \/
OpMod           \%
POpen            \(
PClose            \)
et un fichier de description de la grammaire (.y)
exemple (partie) :
C#:
%token INTEGER, FLOAT, OP_PLUS, OP_MINUS, OP_MULT, OP_DIV, OP_MOD, P_OPEN, P_CLOSE

%%

line   : exp                            { Console.WriteLine("result is {0}\n", $1.n);}
       ;

exp    : term                           { $$.n = $1.n;            Console.WriteLine("Rule -> exp: {0}", $1.n); }
       | exp OP_PLUS term               { $$.n = $1.n + $3.n;    Console.WriteLine("Rule -> exp: {0} + {1}", $1.n, $3.n); }
       | exp OP_MINUS term              { $$.n = $1.n - $3.n;    Console.WriteLine("Rule -> exp: {0} - {1}", $1.n, $3.n); }
       ;

term   : factor                            {$$.n = $1.n;            Console.WriteLine("Rule -> term: {0}", $1.n); }
       | term OP_MULT factor            {$$.n = $1.n * $3.n;    Console.WriteLine("Rule -> term: {0} * {1}", $1.n, $3.n); }
       | term OP_DIV factor             {$$.n = $1.n / $3.n;    Console.WriteLine("Rule -> term: {0} / {1}", $1.n, $3.n); }
       ;

factor : float                          {$$.n = $1.n;            Console.WriteLine("Rule -> factor: {0}", $1.n); }
       | P_OPEN exp P_CLOSE             {$$.n = $2.n;            Console.WriteLine("Rule -> factor: ( {0} )", $3.n);}
       ;

number :
       | NUMBER                            { Console.WriteLine("Rule -> number: {0}", $1.n); }
       ;
float  :
       | FLOAT                            { Console.WriteLine("Rule -> float: {0}", $1.n); }
       ;
Les deux fichiers dans un premier temps vont être compilés et générer des fichiers source du langage ( dans mon cas c'est du dotnet) dans lequel on doit faire l'analyse d'une ligne source (équivalent existe en python, java, c mais pas en vba) .
LexYacc.png

Voici ce que j'obtiens en mettant comme source :
Code:
(45.0*2.8)/((1.0*1.04)/(0.8*(1.1-0.3)))

token: (
token: 45.0
Rule -> float: 45
Rule -> factor: 45
Rule -> term: 45
token: *
token: 2.8
Rule -> float: 2,8
Rule -> factor: 2,8
Rule -> term: 45 * 2,8
token: )
Rule -> exp: 126
Rule -> factor: ( 2,8 )
Rule -> term: 126
token: /
token: (
token: (
token: 1.0
Rule -> float: 1
Rule -> factor: 1
Rule -> term: 1
token: *
token: 1.04
Rule -> float: 1,04
Rule -> factor: 1,04
Rule -> term: 1 * 1,04
token: )
Rule -> exp: 1,04
Rule -> factor: ( 1,04 )
Rule -> term: 1,04
token: /
token: (
token: 0.8
Rule -> float: 0,8
Rule -> factor: 0,8
Rule -> term: 0,8
token: *
token: (
token: 1.1
Rule -> float: 1,1
Rule -> factor: 1,1
Rule -> term: 1,1
token: -
Rule -> exp: 1,1
token: 0.3
Rule -> float: 0,3
Rule -> factor: 0,3
Rule -> term: 0,3
token: )
Rule -> exp: 1,1 - 0,3
Rule -> factor: ( 0,3 )
Rule -> term: 0,8 * 0,8
token: )
Rule -> exp: 0,64
Rule -> factor: ( 0,3 )
Rule -> term: 1,04 / 0,64
token: )
Rule -> exp: 1,625
Rule -> factor: ( 0,3 )
Rule -> term: 126 / 1,625
Rule -> exp: 77,5384615384615
result is 77,5384615384615
je ne maîtrise pas encore tout (par exemple je ne sais pas pour l'instant mixer des entiers et des flottants , c'est pour cela que ma ligne
source n'est composée que de flottants.

Ami calmant, J.P
 
Dernière édition:
re
Bonjour @jurassic pork tu m'a l'air bien parti
moi je cherche la logique vba pour mettre des parenthèses en fonction des priorités
par exemple j'ai "3*2*8*2"
et je dois lui mettre les parenthèses en fonction des priorités
pour pouvoir la repasser par mon moteur html
une ébauche
VB:
Sub test()
    chaine = "3*2*8*2"
    chaine = Replace(chaine, "*", "|*")
     Do While InStr(chaine, "*") > 0
      t = Split(chaine, "|")
     For i = 1 To UBound(t)
            If InStr(t(i), "*") Then t(i - 1) = "(" & t(i - 1):  t(i - 1) = t(i - 1) & Replace(t(i), "*", "x") & ")": t(i) = "": Exit For
        Next
        chaine = Replace(Join(t, ""), "*", "|*")
   Debug.Print chaine
   Loop
MsgBox chaine
End Sub
resultat dans la console

(3x2)|*8|*2
((3x2)x8)|*2
(((3x2)x8)x2)
ca me parait bon vous me direz
 
allez plus compliqué dites moi si les parenthèses dans la console sont bien représentatives des priorités
VB:
Sub test()
    chaine = "3*2*8+10*2-4*2"
    Debug.Print chaine
    Debug.Print "--------------------"
    For Each elem In Array("+", "-", "*", "/"): chaine = Replace(chaine, elem, "|" & elem): Next
    Do While InStr(chaine, "*") > 0
        t = Split(chaine, "|")
        For i = 1 To UBound(t)
            If InStr(t(i), "*") Then t(i - 1) = "(" & t(i - 1): t(i - 1) = t(i - 1) & Replace(t(i), "*", "x") & ")": t(i) = "": Exit For
        Next
        chaine = Replace(Replace(Replace(Join(t, ""), "*", "|*"), "+", "|+"), "-", "|-")
        Debug.Print chaine
    Loop
    chaine = Replace(Replace(chaine, "(|+", "+("), "(|-", "-(")
    Debug.Print chaine
    MsgBox chaine
End Sub
la console
3*2*8+10*2-4*2
--------------------
(3x2)|*8|+10|*2|-4|*2
((3x2)x8)|+10|*2|-4|*2
((3x2)x8)(|+10x2)|-4|*2
((3x2)x8)(|+10x2)(|-4x2)
((3x2)x8)+(10x2)-(4x2)
si c'est bon je compile ça en fonction au propre
 
3*2*8+10*2-4*2
--------------------
(3x2)|*8|+10|*2|-4|*2
((3x2)x8)|+10|*2|-4|*2
((3x2)x8)(|+10x2)|-4|*2
((3x2)x8)(|+10x2)(|-4x2)
((3x2)x8)+(10x2)-(4x2)

si c'est bon je compile ça en fonction au propre
Hello Patrick,
j'ai soumis ton expression à mon analyseur, apparemment on arrive au même résultat :
token: 3.0
Rule -> float: 3
Rule -> factor: 3
Rule -> term: 3
token: *
token: 2.0
Rule -> float: 2
Rule -> factor: 2
Rule -> term: 3 * 2
token: *
token: 8.0
Rule -> float: 8
Rule -> factor: 8
Rule -> term: 6 * 8
token: +
Rule -> exp: 48
token: 10.0
Rule -> float: 10
Rule -> factor: 10
Rule -> term: 10
token: *
token: 2.0
Rule -> float: 2
Rule -> factor: 2
Rule -> term: 10 * 2
token: -
Rule -> exp: 48 + 20
token: 4.0
Rule -> float: 4
Rule -> factor: 4
Rule -> term: 4
token: *
token: 2.0
Rule -> float: 2
Rule -> factor: 2
Rule -> term: 4 * 2
Rule -> exp: 68 - 8
result is 60
 
Bonjour @jurassic pork
bon on est bons alors
maintenant on essaie une division dans le lot
VB:
Sub test()
    chaine = "3*2*8*4.5+10/1.5*2-4*2"
    Debug.Print chaine
    Debug.Print "--------------------"
    For Each elem In Array("+", "-", "*", "/"): chaine = Replace(chaine, elem, "|" & elem): Next
    Do While InStr(chaine, "*") > 0
        t = Split(chaine, "|")
        For i = 1 To UBound(t)
            If InStr(t(i), "*") Then t(i - 1) = "(" & t(i - 1): t(i - 1) = t(i - 1) & Replace(t(i), "*", "x") & ")": t(i) = "": Exit For
        Next
        chaine = Replace(Replace(Replace(Replace(Join(t, ""), "*", "|*"), "+", "|+"), "-", "|-"), "/", "|/")
        Debug.Print chaine
    Loop
    chaine = Replace(Replace(Replace(chaine, "(|+", "+("), "(|-", "-("), "(|/", "/(")
    chaine = Replace(chaine, "|", "")
    Debug.Print chaine
    MsgBox chaine
End Sub
resultat dans la console
3*2*8*4.5+10/1.5*2-4*2
--------------------
(3x2)|*8|*4.5|+10|/1.5|*2|-4|*2
((3x2)x8)|*4.5|+10|/1.5|*2|-4|*2
(((3x2)x8)x4.5)|+10|/1.5|*2|-4|*2
(((3x2)x8)x4.5)|+10(|/1.5x2)|-4|*2
(((3x2)x8)x4.5)|+10(|/1.5x2)(|-4x2)
(((3x2)x8)x4.5)+10/(1.5x2)-(4x2)
c'est bon ou il faut faire comme pour "X"
 
re j'ai fini par trouver mon astuce
VB:
Sub test()
    chaine = "3*2*8*4.5+10/1.5*2-4*2"
    Debug.Print chaine
    Debug.Print "--------------------"
    Debug.Print PutPrioritySegment(chaine)
End Sub
Function PutPrioritySegment(chaine)
    Dim elem, i&, t
    For Each elem In Array("+", "-", "*", "/"): chaine = Replace(chaine, elem, "|" & elem): Next
    chaine = Replace(chaine, "/", "*/")
    Do While InStr(chaine, "*") > 0
        t = Split(chaine, "|")
        For i = 1 To UBound(t)
            If InStr(t(i), "*") Then t(i - 1) = "(" & t(i - 1): t(i - 1) = t(i - 1) & Replace(t(i), "*", "x") & ")": t(i) = "": Exit For
        Next
        chaine = Replace(Replace(Replace(Replace(Join(t, ""), "*", "|*"), "+", "|+"), "-", "|-"), ":", "|:")
        Debug.Print chaine
    Loop
    chaine = Replace(Replace(Replace(chaine, "(|+", "+("), "(|-", "-("), "(|:", "/(")
    chaine = Replace(chaine, "(+", "+(")
    chaine = Replace(chaine, "x/", "/")
    chaine = Replace(chaine, "|", "")
    PutPrioritySegment = chaine
End Function

3*2*8*4.5+10/1.5*2-4*2
--------------------
(3x2)|*8|*4.5|+10|*/1.5|*2|-4|*2
((3x2)x8)|*4.5|+10|*/1.5|*2|-4|*2
(((3x2)x8)x4.5)|+10|*/1.5|*2|-4|*2
(((3x2)x8)x4.5)(|+10x/1.5)|*2|-4|*2
(((3x2)x8)x4.5)((|+10x/1.5)x2)|-4|*2
(((3x2)x8)x4.5)((|+10x/1.5)x2)(|-4x2)
(((3x2)x8)x4.5)+((10/1.5)x2)-(4x2)
1740767842747.png




1740767970555.png
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
17
Affichages
782
Réponses
9
Affichages
275
Réponses
3
Affichages
77
Retour