Itération VBA

Résolu
Bonjour,

Je suis débutante en VBA et je dois écrire une macro qui retrouve une variable par itération:

je connais P
je connais la formule pour trouver Px = ((2 * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8) / (-(Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) + ((Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) ^ 2 - 4 * ((T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt1 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt2) * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8)) ^ 0.5)) ^ 4 * 10) * 1000
Je connais toutes les variables sauf T et je veux le retrouver par itération.

La macro serait un peu comme ceci:
Tmin=-0.5
Tmax=100
Tant que P différent de Px
Alors T=100-Dx
et Px= ((2 * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8) / (-(Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) + ((Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) ^ 2 - 4 * ((T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt1 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt2) * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8)) ^ 0.5)) ^ 4 * 10) * 1000
retourner T quand P= Px

Si quelqu'un pouvait m'aider se serait super car ça fait une semaine que j'essaie sans trouver la solution.

Merci a tous

7 réponses

  1. Contributeur
    Bonjour,
    Je ne suis certainement pas un "super doué" :ooo) mais avec une boucle d'itération tu devrais pourvoir y arriver ? et ça pourrait prendre un "certain temps"
    Note1 : Je comprend rien à ta formule mais là n'est pas le problème.
    Note2: ton explication est pas fort clair.
    A+
    1. Bonjour lermite222,

      alors pour la note1: la formule n'est pas importante
      pour simplifier on peut dire que j'ai x= ay
      je connais x (placée en C5) et je veux trouver y(placée en C7)

      j'essaie de créer un programme qui fasse prendre plusieur valeur à y jusqu'a ce qu'il touve le bon x et qu'il me retourne cette valeur de y dans la cellule c7

      j'ai essayé avec la boucle tant que, Do..Loop

      mais je n'y arrive pas!!!

      ==> j'espère avoir été un peu plus clair?
      1. Contributeur
        Oui, mais quel est la grandeur de la variable ? ... 0,1 , 0,000001 ? où ???
      2. les grandeurs des variables x et y sont de 0.01
    2. bonjour

      Tant que P différent de Px me parait optimiste vu les calculs ...
      je crois qu'il vaudrait mieux, si E est l'incertitude sur Px souhaitée, quelque chose du genre
      T = TMax
      Tant que valeur_absolue(P-Px) > E  et T > TMin
        Px = Ta_formule
        T = T-Dx
      fin tant que
      si valeur_absolue(P-Px) < E 
      alors afficher T
      sinon afficher pas trouvé

      bon courage
      1. Bonjour
        merci ccm81, ta macro fonctionne bien mais à chaque fois j'obtient "pas trouvé"
        je pense que c'est à cause du pas qui est trop grand
        voici un copier coller de la macro

        Sub Iteration()

        Pt1 = 1167.0521452767
        Pt2 = -724213.16703206
        Pt3 = -17.073846940092
        Pt4 = 12020.82470247
        Pt5 = -3232555.0322333
        Pt6 = 14.91510861353
        Pt7 = -4823.2657361591
        Pt8 = 405113.40542057
        Pt9 = -0.23855557567849
        Pt10 = 650.17534844798
        Tk = 273.15

        P = Range("c5")

        T = TMax
        While Abs(P - Px) > E And T > TMin
        Px = ((2 * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8) / (-(Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) + ((Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) ^ 2 - 4 * ((T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt1 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt2) * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8)) ^ 0.5)) ^ 4 * 10) * 1000
        T = T - Dx
        Wend
        If (P - Px) < E Then
        Range("c7") = T
        Else: Range("c7") = "pas trouvé"
        End If

        End Sub

        Que dois-je améliorer?

        Merci!
        1. re
          as tu attribué une valeur à la précision souhaitée E, ici, je ne la vois pas donc, comme vba prend des initiatives, il prend E=0,et tu reviens au cas précédent !!!! ( commence par E assez grand pour tester puis diminue sa valeur vers la précision souhaitée pour ton résultat)
          bonne suite
        2. RQ1. il te faudrait toujours declarer les variables utilisées
          Dim Pt1 as double
          etc ..
          RQ2 et pour eviter d'oublier tu commences toujours ton module (avant toute procedure) par
          Option Explicit
          RQ3. une fois que ça fonctionne pour une valeur de E,
          si pour une valeur de E plus petite, ça donne "pas trouvé" et que ça ne te convient pas, alors il faudra aussi diminuer le pas
          RQ4. Il y a aussi Dx, TMax et TMin qui n'ont pas de valeur
      2. re
        dans la boucle tantque, la première fois qu'on rentre dans la boucle, Px n'est pas connue, donc il faut soit calculer une fois Px avant, soit, ce qui est préférable, utiliser une boucle jusqu'à

        initialiser TMin, TMax, Dx, E, et tes variables   
        T = TMax+Dx   
        do   
          T = T-Dx   
          Px = Ta_formule   
        loop until valeur_absolue(P-Px) < E or T < TMin   
        si valeur_absolue(P-Px) < E    
        alors afficher T   
        sinon afficher pas trouvé


        RQ. les remarques précédentes restent valables

        ce qui donne

        Sub Iteration()
        
        Const E = 0.1
        
        Dim Pt1, Pt2, Pt3, Pt4, Pt5, Pt6, Pt7, Pt8, Pt9, Pt10, Tk, Px, P
        Dim TMin, TMax, T, Dx
        
        Pt1 = 1167.0521452767
        Pt2 = -724213.16703206
        Pt3 = -17.073846940092
        Pt4 = 12020.82470247
        Pt5 = -3232555.0322333
        Pt6 = 14.91510861353
        Pt7 = -4823.2657361591
        Pt8 = 405113.40542057
        Pt9 = -0.23855557567849
        Pt10 = 650.17534844798
        Tk = 273.15
        
        P = Range("c5")
        TMin = -0.5
        TMax = 100
        Dx = 0.01
        
        T = TMax + Dx
        Do
          T = T - Dx
          Px = ((2 * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8) / (-(Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) + ((Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) ^ 2 - 4 * ((T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt1 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt2) * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8)) ^ 0.5)) ^ 4 * 10) * 1000
        Loop Until Abs(P - Px) < E Or T < TMin
        
        If (P - Px) < E Then
          Range("c7") = T
        Else
          Range("c7") = "pas trouvé"
        End If
        
        End Sub

        et avec les valeurs qui sont dans le code
        pour P = 750 ça donne T = 91.76

        bonne suite
        1. re,

          alors tout d'abord un grand merci pour toutes tes remarques, j'en tiendrait compte pour le reste de mon programme.
          Ta macro fonctionne très bien
          J'ai quelques petites questions pour bien la comprendre et pouvoir faire de nouvelles itérations:

          Q1:
          T = TMax + Dx
          Je ne comprend pas à quoi sert la première ligne, est elle obligatoire?

          Q2:
          Do
          T = T - Dx
          Px = ((2 * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8) / (-(Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) + ((Pt3 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt4 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt5) ^ 2 - 4 * ((T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt1 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt2) * (Pt6 * (T + Tk + Pt9 / (T + Tk - Pt10)) ^ 2 + Pt7 * (T + Tk + Pt9 / (T + Tk - Pt10)) + Pt8)) ^ 0.5)) ^ 4 * 10) * 1000
          Loop Until Abs(P - Px) < E Or T < TMin

          là il s'agit de la boucle
          on commence par T = Tmax+Dx-Dx puis on enlève Dx à chaque boucle jusqu'à être infèrieur à E ou que T soit inférieur à Tmin?
          la dernière ligne donne en fait les conditions pour sortir de la boucle et ne pas planté le pc
      3. re

        T = TMax+Dx   
        do   
          T = T-Dx   
          Px = Ta_formule   
        loop until valeur_absolue(P-Px) < E or T < TMin


        le T = T+Dx est une 'ruse' qui permet de commencer la boucle par T = T-Dx (donc, comme tu las compris, et comme ça doit être, la 1° valeur de T est Tmax) puis de calculer Px avec cette valeur de T
        et quand on sort de la boucle, si bien sur la valeur de Px est bonne, T contient la bonne valeur de T
        RQ1. si on voulait etre vraiment rigoureux, il faudrait même écrire
        T = TMax+Dx   
        do   
          T = T-Dx  
          if T >= TMin then 
            Px = Ta_formule
          end if 
        loop until valeur_absolue(P-Px) < E or T < TMin


        avant de calculer Px (on ne sait jamais, une valeur de T < TMin peut faire planter le calcul)
        ------------------------------------------------------------
        T = TMax 
        do   
          Px = Ta_formule 
          T = T-Dx 
        loop until valeur_absolue(P-Px) < E or T < TMin
        T = T+Dx


        ici, si la valeur en sortie de Px est bonne, T n'est pas la valeur correspondante et il faut ajouter après la sortie de boucle, un T = T+Dx pour rectifier
        comme c'est la bonne valeur de T qui t'interesse, il y a un choix a faire entre les deux méthodes
        RQ2. avec cette solution, la RQ1 précedente n'a plus lieu d'être, comme quoi .....
        ces pb controles de boucles tantque ou jusqua sont toujours un peu délicats à gérer

        bon courage pour la suite

        PS. si ce n'est pas indiscret, ta formule, elle sert à quoi?
        1. D'accord je comprend mieux.
          Cette formule entre dans un programme de thermodynamique de l'air humide.
          Elle me sert à retrouver la température de mon air grâce à ma température de vapeur saturante!!
          En tout cas je te remercie pour ces informations, ça m'aide beaucoup!!
        2. vaste programme
          si c'est fini pour moi, tu mets le pb a résolu
          bonne suite
        3. ok je le met de suite

          merci
        4. Bonjour ccm81,

          j'ai de nouveau un petit problème avec cette itération car pour être très précise il faut que l'ordinateur "réfléchisse" un long moment.
          Du coup, ce que j'avais pensé faire c'est de commencé la formule pour temp=50 et d'avoir un Dx= (1+(1-pvsx/pvs *0.1 )
          j'ai essayé avec cette macro:
          Function iterationT(Pvs)
          Const C = 0.000000000001

          Pt1 = 1167.0521452767
          Pt2 = -724213.16703206
          Pt3 = -17.073846940092
          Pt4 = 12020.82470247
          Pt5 = -3232555.0322333
          Pt6 = 14.91510861353
          Pt7 = -4823.2657361591
          Pt8 = 405113.40542057
          Pt9 = -0.23855557567849
          Pt10 = 650.17534844798
          Tk = 273.15
          TempMin = -0.5
          TempMax = 200
          TempMoy = 50
          Dx = (1 + (1 - (Pvsx / Pvs) * 0.1))

          Do
          Temp = Temp - Dx
          Pvsx = ((2 * (Pt6 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) ^ 2 + Pt7 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) + Pt8) / (-(Pt3 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) ^ 2 + Pt4 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) + Pt5) + ((Pt3 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) ^ 2 + Pt4 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) + Pt5) ^ 2 - 4 * ((Temp + Tk + Pt9 / (Temp + Tk - Pt10)) ^ 2 + Pt1 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) + Pt2) * (Pt6 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) ^ 2 + Pt7 * (Temp + Tk + Pt9 / (Temp + Tk - Pt10)) + Pt8)) ^ 0.5)) ^ 4 * 10) * 1000
          Loop Until Pvs - Pvs < C Or Temp < Tmin Or Temp > TempMax

          If (Pvs - Pvsx) < C Then
          iterationT = Temp
          Else
          iterationT = "pas trouvé"
          End If
          End Function

          mais l'ordinateur beuge à chaque fois...
          Est ce que tu vois d'ou l'erreur peut provenir?

          Merci
      4. bonjour
        je ne suis pas chez moi, donc, je n'ai plus le pb sous la main, et pas trop le temps ..
        à priori je vois quelques erreurs
        1. avant la boucle do
        - Dx est calculé en fonction de pvsx qui, a ce moment n'a pas encore de valeur
        - C me parait bien petit
        -Temp n'a pas été initialisé (à TempMax ?)
        2. dans le controle, de la boucle (loop until ...)
        - le test pvs-pvs<C est problématique, 2 fois pvs et tester plutot la valeur absolue : abs(pvsx-pvs)
        - tu utilises TMin alors que c'est TempMin qui est initialisé plus haut

        RQ1. pour eviter d'utiliser des variables 'accidentelles' tu met Option Explicit en début de module, avec cette option, le compilateur refusera toute variable non déclarée
        RQ2. conséquence, tu devras déclarer toutes tes variables après la ligne de déclaration de la fonction (Dim Temp as single , etc ...)
        RQ3. les Ptx sont des constantes à déclarer comme C

        bonne suite
        1. d'accord merci pour tes conseils..j'ai réussi à corriger l'itération
          Merci!