Dépassement de capacité annormal

Résolu
ezor Messages postés 190 Statut Membre -  
ezor Messages postés 190 Statut Membre -
Bonjour à toutes et à tous,

Je suis entrain de programmer un petit outils pour calculer la probabilité de gagner dans un jeu.
Le principe est simple : deux joueurs A et B tirent aléatoirement un jeton parmis 4. La probabilité de gagner un point est de 1/4. Ma fonction prend en argument le score en cours de chaque joueur, ainsi que le nombre restant de coup pour chacun (ils ne jouent pas forcement à tour de rôle).
bref, tout ça n'est pas forcement très important.
Je vous mets le code que j'ai déjà fait et je vous explique le problème après ;)

Dim a As Long
Dim x As Long
Dim b As Long
Dim y As Long
Dim res As Double
Dim som As Double
Dim k As Long



Sub calcul()
a = Range("C4").Value 'Score du joueur A
x = Range("C5").Value 'nombre de coup restant pour le joueur A
b = Range("D4").Value 'Score du joueur B
y = Range("D5").Value 'nombre de coup restant pour le joueur B

If a + x <= b Then
res = 0    'cas trivial, A est sur de perdre, donc proba à 0 directement

ElseIf a > b + y Then
res = 1    'cas trivial, A est sur de gagner, donc proba à 1 directement


ElseIf a > b Then

'à finir



ElseIf a < b Then
res = 0
k = 0
While k <= a - b + x - 1
som = 0
    For i = (b - a + 1 + k) To x
    som = som + proba(i, x)
    Next i

    res = res + proba(k, y) * som

k = k + 1
Wend


ElseIf a = b Then

    If x = y Then
       res = 0.5 'cas trivial aussi, donc 0.5 directement
    Else
     'à finir aussi
    End If


Else
MsgBox "j'ai oublié un cas"

End If


Cells(4, 6) = res 'affiche le résultat dans une case
MsgBox ("terminé")


End Sub



'fonction calculant la probabilité de faire n "réponses justes" parmis les r chances restantes
Public Function proba(nb_juste, restant) As Long
Dim r As Long
Dim n As Long

r = restant
n = nb_juste
fact (r) * 3 ^ (r - n) / ((4 ^ n) * fact(n) * (fact(r - n)))

End Function



'implémentation de la fonction "factorielle" 

Public Function fact(ByVal n As Long) As Long

If n < 0 Then
MsgBox "erreur : argument factorielle négatif "
Exit Function

ElseIf n = 0 Then
fact = 1

Else
    If n = 1 Then
    fact = 1

    Else
    fact = n * fact(n - 1)

    End If

End If

End Function



Comme vous pouvez le constater, il manque pas mal de cas, mais j'ai déjà un problème avec le seul qui est déjà fait (ie le cas où a<b). En effet, en faisant le test, j'ai le message suivant lorsque j'execute la macro :

"erreur : dépassement de capacité"
Je me suis un peu renseigné, et il semble que cela signifie que l'on attein les limites du type de la variable. Mais ici, il s'agit de variables de type Long et Double. J'ai du mal à croire que je dépasse les 32octets avec des calculs que l'on peut faire avec une calculatrice de collège !
J'ai déjà essayer de convertir les variables avec des CLng() et CDbl() mais sans résultat.

Autre chose que j'ai remarqué. Si, dans la routine de la fonction "factorielle", je ne met pas le ByVal pour l'argument, j'ai directement des messages de la MsgBox qui m'indiquent que je suis dnas le cas où n<0...alors que le calcul de la routine principal n'en demande normalement pas.

Voilà, j'espère avoir été à peu près clair.
je vous remercie d'avance pour votre aide

PS : pour ceux qui se demande quel est le but de tout ça je vous dis juste que je suis en stage, au mois d'aout, dans un openspace...
PPS : impossible de mettre une coloration convenable sur el code, mais de là où je suis, je ne peux rien faire. désolé

ezor

6 réponses

  1. NHenry Messages postés 15235 Date d'inscription   Statut Modérateur Dernière intervention   387
     
    Regardes la valeur des variables en pas à pas (F9 pour le point d'arrêt et Shift+F9 sur la sélection pour voir la valeur
    0
    1. ezor Messages postés 190 Statut Membre 11
       
      merci pour ta réponse rapide.
      Je ne comprend pas bien ce que tu dis. J'arrive bien à mettre un point d'arrêt sur une ligne, mais après avoir lancé la macro, si je fais Shift+F9, ça me revoit "pas d'expression espionne selectionnée" ou "expression espionne incorrecte".

      Et le deboggeur pas à pas ne se lance pas bien (mais ici j'ai la version office 2003 seulement, ceci explique peut être cela)
      0
  2. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Bonjour,

    Afin de pouvoir tester, merci de nous donner les valeurs (qui font planter la procédure) de :
    - Range("C4")
    - Range("C5")
    - Range("D4")
    - Range("D5")
    0
    1. ezor Messages postés 190 Statut Membre 11
       
      le but est d'aller jusqu'à 20. Mais ça me renvoie une erreur dès que A>2 ou 3 (toujours en gadant a<b et a+x>b)
      par exemple avec
      - Range("C4") = 2
      - Range("C5") = 3
      - Range("D4") = 4
      - Range("D5") = 3
      la procédure plante
      0
  3. pijaku Messages postés 13513 Date d'inscription   Statut Modérateur Dernière intervention   2 773
     
    Premier souci : la fonction proba ne renvoie rien.
    Pourquoi?
    Parce que tu ne lui affectes aucun résultat...
    Public Function proba(nb_juste, restant) As Long
    Dim r As Long
    Dim n As Long
    
    r = restant
    n = nb_juste
    'ICI on lui affectes un résultat... (tu avais oublié proba =
    proba = fact(r) * 3 ^ (r - n) / ((4 ^ n) * fact(n) * (fact(r - n)))
    End Function 

    0
  4. ccm81 Messages postés 11033 Statut Membre 2 434
     
    Bonjour

    Le dépassement vient de ta façon d'implémenter la fonction proba : fact(r) ou fact(n) peut être trop grand pour un entier long
    fact(r)/(fact(n)*fact(r-n)) = (r,n) nb de combinaisons de n parmi r
    Excel vba dispose de la fonction de la feuille de calcul Combin

    Remplaces la ligne (au passage tu as oublié proba = )
    ' proba = fact(r) * 3 ^ (r - n) / ((4 ^ n) * fact(n) * (fact(r - n)))
    par celle ci
    proba = Application.WorksheetFunction.Combin(r, n) * 3 ^ (r - n) / 4 ^ n

    tu pourras aller un peu plus loin, et tu n'as plus besoin de ta fonction fact

    Cordialement
    0
    1. ccm81 Messages postés 11033 Statut Membre 2 434
       
      Cordiales salutations à NHenry et à pijaku au passage

      je me suis permis de faire un peu de ménage

      Sub calcul()
      Dim a As Long
      Dim x As Long
      Dim b As Long
      Dim y As Long
      Dim res As Double
      Dim som As Double
      Dim k As Long
      Dim i As Long
      a = Range("C4").Value 'Score du joueur A
      x = Range("C5").Value 'nombre de coup restant pour le joueur A
      b = Range("D4").Value 'Score du joueur B
      y = Range("D5").Value 'nombre de coup restant pour le joueur B
      If a + x <= b Then
        res = 0    'cas trivial, A est sur de perdre, donc proba à 0 directement
      ElseIf a > b + y Then
        res = 1    'cas trivial, A est sur de gagner, donc proba à 1 directement
      ElseIf a > b Then
        'à finir
      ElseIf a < b Then
        res = 0
        k = 0
        While k <= a - b + x - 1
          som = 0
          For i = (b - a + 1 + k) To x
            som = som + proba(i, x)
          Next i
          res = res + proba(k, y) * som
          k = k + 1
        Wend
      ElseIf a = b Then
        If x = y Then
           res = 0.5 'cas trivial aussi, donc 0.5 directement
        Else
          'à finir aussi
        End If
      Else
        MsgBox "j'ai oublié un cas"
      End If
      Cells(4, 6) = res 'affiche le résultat dans une case
      MsgBox ("terminé")
      End Sub
      
      'fonction calculant la probabilité de faire n "réponses justes" parmis les r chances restantes
      Public Function proba(nb_juste As Long, restant As Long) As Long
      Dim r As Long
      Dim n As Long
      r = restant
      n = nb_juste
      '?????? j'ai ajouté le renvoi du résultat ---> proba =
      ' proba = fact(r) * 3 ^ (r - n) / ((4 ^ n) * fact(n) * (fact(r - n)))
      proba = Application.WorksheetFunction.Combin(r, n) * 3 ^ (r - n) / 4 ^ n
      End Function
      0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. ezor Messages postés 190 Statut Membre 11
     
    Autant de réponse en si peu de temps, merci beaucoup à tous.

    Effectivement, j'ai oublié le "proba =" !

    Pour le calcul de n parmis r (oui, c'est bien ce que je voulais faire) je n'avais pas trouvé de fonction vba qui faisait déjà tout ça, c'est pourquoi j'ai voulu repasser par les factorielles du dénombrement. Merci pour le conseil.

    Je vais tester ça au plus vite et je vous dis ce qu'il en est.
    0
  7. ezor Messages postés 190 Statut Membre 11
     
    Merci à tous pour votre aide, j'ai fini par faire fonctionner tout ça.

    Au passage, il y avait une autre erreur : je definissais le résultat de proba comme un Long au lieu d'un Double (donc toutes les proba étaient à 0)
    0