Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
483 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  Boucle infini (VBA)

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Boucle infini (VBA)

n°2204445
floponizuk​a
Posté le 27-09-2013 à 18:43:10  profilanswer
 

Bonjour,
 
Je suis débutant en  VBA et voilà déjà ma première boucle infini, il semblerait que ma boucle for se passe mal.
 
Pouvez vous m'éclairer?
 
Sub Méthode1()
    Dim epsilon As Double
    Dim r As Double
    Dim M As Integer
    Dim c As Integer
    Dim N As Integer
    Dim P As Double
    Dim j As Integer
    r = 0
    M = 5
    c = 5
    N = 100
    P = 80
    epsilon = 1
     
    While (epsilon > 0.1)
     
    S = 0
    For j = 1 To 5
        S = S + c / ((1 + r) ^ i)
        Next j
        S = S + N / ((1 + r) ^ M)
    epsilon = Abs(P - S)
    r = r + 0.01
    Wend
     
    MsgBox (r)
     
     
End Sub
 
//En tout cas je vous remercie.

mood
Publicité
Posté le 27-09-2013 à 18:43:10  profilanswer
 

n°2204452
Marc L
Posté le 27-09-2013 à 19:46:00  profilanswer
 

 
           Bonjour,
 
           merci d'utiliser la prochaine fois l'icône C dédiée au code …   Une bonne indentation est aussi appréciée.
 
           En regardant donc juste la condition de la boucle, epsilon est toujours supérieur à 0.1 empêchant la sortie de la boucle …
           Prévoir peut-être un nombre maximum d'itérations, non ?
 
           Ce serait judicieux de tout mettre à plat, entre un schéma en langage courant,
           la sémantique de ce qu'est censé faire le code, et en comparant si chaque ligne de code correspond bien à ce schéma …


Message édité par Marc L le 27-09-2013 à 19:48:20
n°2204458
floponizuk​a
Posté le 27-09-2013 à 22:02:13  profilanswer
 

Désolé, effectivement, c'est la première fois que je poste.
 
ça m'étonne un peu d'avoir toujours epsilon>0.1 puisque je cherche à résoudre une équation dont je connais une solution approximative r=0.11 avec les paramètres que j'ai choisi.
 
(Je ne sais pas si on peut mettre du LaTeX ici.) Mais c'est:
 
P-c/(1+r)-...-c/((1+r)^5)- N / ((1 + r) ^ M)=0
 
Et ceci tend vers P>0 quand r tend vers l'infini et ça vaut P-5c-N<0 en r=0, alors cette valeur de r je suis sûr qu'elle existe.
 
Mais il est possible que ce soit mon algo qui soit faux.
 
Du coup mettre un nombre maximum d'itérations ne m'intéresse pas trop.

n°2204465
Marc L
Posté le 28-09-2013 à 02:20:37  profilanswer
 

 
           Epsilon reste bloqué vers les 55, donc méthode à revoir …
 
           Pour pouvoir le vérifier, ajouter les deux lignes suivantes juste avant le  Wend :

Code :
  1.     Debug.Print epsilon
  2.     DoEvents


           La progression d'epsilon en direct dans la fenêtre Exécution ! …
 

n°2204473
floponizuk​a
Posté le 28-09-2013 à 11:43:48  profilanswer
 

Bonjour,
 
Merci en fait j'ai reprogrammé ça dans un autre langage pour vérifier. Et j'ai vu que l'algo était bon.
L'erreur vient en fait parce que j'ai oublié de déclarer S.
 
J'ai un peu honte.

n°2204476
Marc L
Posté le 28-09-2013 à 12:31:06  profilanswer
 

 
           En double ?  Sinon pas de honte à avoir …
 
           L'instruction Option Explicit en début de module permet d'éviter ce problème en obligeant de déclarer les variables
           ou encore en cochant la case Déclaration des variables obligatoire dans les Options de l'environnement VBA.
 
           DoEvents permet de pouvoir garder la main pour interrompre la boucle …


Message édité par Marc L le 28-09-2013 à 12:34:55
n°2204479
floponizuk​a
Posté le 28-09-2013 à 13:59:04  profilanswer
 

Oui c'est ça il manque un:
Dim S As Double
Et dans le code que j'ai mis ici il y a une autre erreur, j'ai oublié de modifier le i en j.
Merci pour ces conseils, je vais les utiliser, ça va m'éviter des difficultés.
 

n°2204549
Marc L
Posté le 29-09-2013 à 11:20:07  profilanswer
 

 
           Avec seulement ces corrections, la boucle ne s'arrêtera pas plus avec le pas de r de 0.01
           vu que r doit se trouver entre 0.10 & 0.11, donc obligation d'affiner le pas …
 
           Qui plus est le résultat r de ton code est faussé de +0.01 à cause de la conception de la boucle,
           l'ajout du pas s'effectuant avant le test de sortie …
 
           J'aimerais bien voir ton code qui fonctionne.   Combien d'itérations pour trouver la solution ?
 
           De mon côté ma version avec la résolution de 0.1 n'a besoin que de 6 itérations pour la trouver, 9 pour 0.01 et 18 pour 0.001 …
 

n°2204564
floponizuk​a
Posté le 29-09-2013 à 14:49:19  profilanswer
 

Oui de toute façon je voulais une solution un peu plus précise, voici mon code, je ne l'ai pas du tout optimisé car je ne cherchais qu'à comparer une approximation grossière mais qui se fait à l'aide d'un simple calcul  avec cette méthode qui me donne pratiquement la solution exact à mon équation.
Mais en tout cas, je vois que votre méthode semble très rapide, vous utilisez une dichotomie?
Mais, je me dis que dans ce cas là, il faut avoir une petite idée de ce que vaut r?
 
Sub Méthode1()
    Dim epsilon As Double
    Dim r As Double
    Dim M As Integer
    Dim c As Integer
    Dim N As Integer
    Dim P As Double
    Dim j As Integer
    Dim S As Double
     
     
    r = 0
    M = 5
    c = 5
    N = 100
    P = 80
    epsilon = 1
     
    While (epsilon > 0.001)
     
    S = 0
    For j = 1 To M
        S = S + c / ((1 + r) ^ j)
        Next j
        S = S + N / ((1 + r) ^ M)
    epsilon = Abs(P - S)
    r = r + 0.000001
    Wend
     
    MsgBox (r)
     
     
End Sub

n°2204580
Marc L
Posté le 29-09-2013 à 17:45:47  profilanswer
 

 
           Il y a pourtant une icône pour le code ‼
 
           Sinon avec la résolution de 0.000001 de ton dernier code, 103 189 itérations sont nécessaires pour terminer le processus.
           Pour éviter le souci de boucle sans fin, je n'autorise pas mes procédures de dépasser les 99 itérations !
 
           Ton résultat est toujours faussé par la position de l'incrémentation de la variable  r  dans la boucle …
 
           J'utilise la même méthode mais en partant d'un pas supérieur pour la variable  r  accélérant donc la procédure
           tout en détectant évidemment le moment où cette variable est trop grande afin d'affiner ce pas.
 
           Désactiver  Option Explicit  ou la Déclaration des variables obligatoire car les variables de mes procédures sont déclarées à la volée
 
           La variable  D  est la résolution de l'approximation des décimales,  A  est le pas de la variable  r  et  F  le résultat de la formule.
 
           La ligne n°12 est la détection pour l'affinage du pas.

Code :
  1. Sub Demo1()
  2.     Const D# = 0.00001, c% = 5, M% = 5, N% = 100, P% = 80
  3.    
  4.     A# = 0.1
  5.    
  6.     Do
  7.         r# = r# + A
  8.         U# = 1 + r
  9.         F# = N / U ^ M
  10.         For j% = 1 To 5:  F = F + c / U ^ j:  Next
  11.         E# = P - F
  12.         If E > D Then r = r - A: A = A / 10
  13.         I% = I% + 1
  14.     Loop While Abs(E) > D And I < 99
  15.    
  16.     MsgBox I & " itérations :" & vbLf & vbLf & "r = " & r & "     F = " & F
  17. End Sub

           En modifiant la variable  D  la valeur de  r  en sera donc plus fine …
           Cette procédure s'avère plus précise que la tienne pourtant avec une résolution moindre !
 
           Mais au lieu de manuellement varier le pas, mieux vaut le faire automatiquement jusqu'à une approximation raisonnable !
           Certes le raisonnable n'est pas toujours scientifique, mais pour des besoins courants,
           une approximation du résultat de la formule de quatre décimales semble suffisante, comme par exemple en gestion / finances ...
           La variable  E  est maintenant de type  Currency  :

Code :
  1. Sub Demo2()
  2.     Const c% = 5, M% = 5, N% = 100, P% = 80
  3.    
  4.     D# = 1
  5.    
  6.     Do
  7.         A# = 0.1
  8.          D = D / 10
  9.         I% = 0
  10.         r# = 0
  11.    
  12.         Do
  13.              r = r + A
  14.             U# = 1 + r
  15.             F# = N / U ^ M
  16.             For j% = 1 To 5:  F = F + c / U ^ j:  Next
  17.             E@ = P - F
  18.             If E > D Then r = r - A: A = A / 10
  19.             I = I + 1
  20.         Loop While Abs(E) > D And I < 99
  21.    
  22.         T$ = T$ & "D = " & D & "   r = " & r & "   (" & P - E & ";)   [" & I & "]" & vbLf & vbLf
  23.     Loop Until E = 0 Or I = 99
  24.    
  25.     MsgBox T
  26. End Sub

           Cette procédure n'a d'autre utilité avec l'augmentation de la résolution de démontrer l'affinage de  r
           jusqu'à atteindre une approximation raisonnable en comparant la progression des itérations nécessaires …
 
           En combinant les deux codes précédents, cette approximation raisonnable est directement calculée en seulement 21 itérations  !

Code :
  1. Sub Demo3()
  2.     Const c% = 5, M% = 5, N% = 100, P% = 80
  3.    
  4.     A# = 0.1
  5.     D# = 0.1
  6.    
  7.     Do
  8.         r# = r# + A
  9.         U# = 1 + r
  10.         F# = N / U ^ M
  11.         For j% = 1 To 5:  F = F + c / U ^ j:  Next
  12.         E@ = P - F
  13.         If Abs(E) <= D And E <> 0 Then D = D / 10
  14.         If E > D Then r = r - A: A = A / 10
  15.         I% = I% + 1
  16.     Loop Until E = 0 Or I = 99
  17.    
  18.     MsgBox I & " itérations :" & vbLf & vbLf & "r = " & r & "     D = " & D
  19. End Sub


           La dichotomie est efficace en l'a contrôlant quelque peu !
 
           Sinon je me demande même sans VBA si le Solveur intégré à Excel suffirait, une autre piste à explorer …

Message cité 1 fois
Message édité par Marc L le 30-09-2013 à 12:20:46
mood
Publicité
Posté le 29-09-2013 à 17:45:47  profilanswer
 

n°2204595
Marc L
Posté le 29-09-2013 à 21:54:17  profilanswer
 

Marc L a écrit :

Cette procédure s'avère plus précise que la tienne pourtant avec une résolution moindre !

             J'ai confondu la résolution et le pas !   Il fallait l'entendre pourtant avec un pas supérieur
 
 
           Sinon voici une variante de la procédure Demo1 apportant une meilleure précision sur la dernière décimale vis à vis de la résolution :

Code :
  1. Sub Demo()
  2.     Const D# = 0.00001, c% = 5, M% = 5, N% = 100, P% = 80
  3.    
  4.     A# = 0.1
  5.     G# = 1
  6.    
  7.     Do
  8.         r# = r# + A
  9.         U# = 1 + r
  10.         F# = N / U ^ M
  11.         For j% = 1 To 5:  F = F + c / U ^ j:  Next
  12.         E# = P - F
  13.         B# = Abs(E)
  14.    
  15.         If B <= D Or S# > 0 Then
  16.             If B < G Then G = B: S = r: X# = F
  17.             T% = B > G Or E > 0
  18.    
  19.         ElseIf E > D Then
  20.             r = r - A
  21.             A = A / 10
  22.         End If
  23.    
  24.         I% = I% + 1
  25.     Loop Until T Or I = 99
  26.    
  27.     MsgBox I & " itérations :" & vbLf & vbLf & "r = " & S & "     F = " & X
  28. End Sub

           Une fois la résolution atteinte, cette procédure va voir si l'Epsilon n'est pas inférieur en incrémentant encore d'un pas,
           on n'est pas à deux / trois itérations près !


Message édité par Marc L le 30-09-2013 à 12:26:18

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  Boucle infini (VBA)

 

Sujets relatifs
Help VBA (sujet annales)problème VBA avec Find/Replace
VBA - couleur texte cellule en fonction du jourVBA/PPT remplacer des données
Help, Algorithme de tri sélectif VBAVBA - Copier données entre deux feuilles et restructuration
[VBA] Remplacer une formule dans plusieurs feuilles du classeurproblème avec une boucle foreach
Boucle FOR et tableauVBA Excel, ouvrir une seule feuille d'un Workbook
Plus de sujets relatifs à : Boucle infini (VBA)


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR