Erreur 400, trop de calculs?

Résolu/Fermé
ezor Messages postés 176 Date d'inscription dimanche 1 mars 2009 Statut Membre Dernière intervention 27 octobre 2016 - Modifié par ezor le 31/08/2015 à 13:30
ezor Messages postés 176 Date d'inscription dimanche 1 mars 2009 Statut Membre Dernière intervention 27 octobre 2016 - 1 sept. 2015 à 10:47
Bonjour,

je cherche à créer une petite macro qui donne la probabilité de victoire pour un jeu aléatoire à deux joueurs. Je rentre le score et le nombre de question restante pour chacun, et je suppose que pour chaque question, il y a 1/4 de réussite.

Le problème est le suivant : Dans certain cas, lorsque je lance la macro depuis la feuille, j'ai "erreur 400" et quand je le fais depuis l'éditeur, j'ai "impossible de lire la propriété combin de la classe WorksheetFunction"
La majorité du temps, ça se passe plutot bien, mais parfois j'ai ces erreurs.

je vous met le code ci dessous

 Dim a As Long
Dim x As Long
Dim b As Long
Dim y As Long
Dim res As Double 'proba de victoire de A
Dim nul As Double 'proba de faire match nul
Dim som As Double
Dim k As Long
Dim i As Long



Sub calcul()
a = Range("C4").Value 'Score du joueur A
x = Range("C5").Value 'nombre de question restante pour le joueur A
b = Range("D4").Value 'Score du joueur B
y = Range("D5").Value 'nombre de question restante pour le joueur B
nul = 0
res = 0

If a + x < b Then
res = 0 'cas trivial où A est sur de perdre

ElseIf a > b + y Then
res = 1 'cas trivial où A est sur de gagner



ElseIf a > b Then

'Calcul de la victoire de A
res = 0
som = 0
k = 0

'Cas où A gagne quelques soit les réponses qu'il fait
For k = 0 To (a - b - 1)
res = res + proba(k, y)
Next k

'Autres cas
k = a - b
While k <= y
som = 0

    For i = k - (a - b) + 1 To x
    som = som + proba(i, x)
    Next i

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

k = k + 1
Wend


'Calcul du match nul
k = 0
While a - b + k <= y
nul = nul + proba(k, x) * proba(a - b + k, y)
k = k + 1
Wend



ElseIf a < b Then
res = 0
nul = 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

'Calcul du match nul
k = 0
While b - a + k <= x
nul = nul + proba(k, y) * proba(b - a + k, x)
k = k + 1
Wend


'cas d'égalité
ElseIf a = b Then

res = 0
nul = 0
    If x = y Then
       For i = 0 To x
       nul = nul + (proba(i, x) ^ 2)
       Next i
       res = (1 - nul) / 2
       
       
    Else 'si a=b mais x =/= y
    Dim min As Integer
    min = Application.WorksheetFunction.min(x, y)


    For k = 0 To min
    som = 0
        For i = (k + 1) To x
        som = som + proba(i, x)
        Next i

    res = res + proba(k, y) * som
    Next k
    
    End If


Else
MsgBox "j'ai oublié un cas"

End If


'écritude du résultat
Cells(4, 6) = res * 100 & " .%"  'probabilité de victoire de A
Cells(7, 6) = nul * 100 & " .%" 'probabilité de match nul
Cells(10, 6) = (1 - res - nul) * 100 & " .%" 'probabilité de victoire de B

Range("F4").NumberFormat = "General"
Range("F7").NumberFormat = "General"
Range("F10").NumberFormat = "General"

res = 0
nul = 0
box = MsgBox("Terminé", vbInformation, "")


End Sub


Public Function proba(nb_juste As Long, restant As Long) As Double
Dim r As Long
Dim n As Long

r = restant
n = nb_juste

proba = (Application.WorksheetFunction.combin(r, n) * 3 ^ (r - n)) / (4 ^ r)
'proba = (combinaison(n,r) * 3 ^ (r - n)) / (4 ^ r)
End Function


Comme vous pouvez le voire, j'ai aussi essayer de créer ma propre fonction "combinaison" pour remplacer COMBIN. Voici comment j'ai fait


'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


'fonction combinaison
Public Function combinaison(ByVal p As Integer,ByVal n As Integer)


If p > n Then
combinaison = 0
Else
combinaison = fact(n) / (fact(p) * fact(n - p))

End If

End Function


mais dans ce cas, j'ai une erreur "dépassement de capacité" au niveau de l'arguement de "combinaison".
j'ai bien l'impression que le problème vient d'un nombre trop grand de calcul à effectuer, mais je ne sais pas comment vérifier ça.

J'espère avoir été à peu près clair dans mes explications.
Je voudrais comprendre d'où viennent vriament ces deux types d'erreurs et si possible comment les régler.

merci d'avance,

PS : voici un exemple de conditions initiales qui entrainent une erreur
Cells(4, 3) = "2"
Cells(4, 4) = "0"
Cells(5, 3) = "15"
Cells(5, 4) = "18"
ezor

4 réponses

michel_m Messages postés 16603 Date d'inscription lundi 12 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2023 3 303
Modifié par michel_m le 31/08/2015 à 13:25
bonjour,
Déjà, remplace "integer" par "long", essaies et tu nous dis

Michel
0
ezor Messages postés 176 Date d'inscription dimanche 1 mars 2009 Statut Membre Dernière intervention 27 octobre 2016 11
31 août 2015 à 13:32
merci pour ta réponse, effectivement, c'est plus "prudent" avec Long, mais le problème reste le même.
0
ccm81 Messages postés 10851 Date d'inscription lundi 18 octobre 2010 Statut Membre Dernière intervention 16 avril 2024 2 404
Modifié par ccm81 le 31/08/2015 à 16:43
Bonjour

Utilises plutôt la fonction combin de la feuille de calcul, qui évitera les factorielles trop grandes, mais tu vas quand même être limité
à 2 147 483 647

Dim c As Long, n As Long, p As Long
n = 5
p = 3
c = Application.WorksheetFunction.Combin(n, p)

Salut à michel en passant

Cdlmnt
0
ezor Messages postés 176 Date d'inscription dimanche 1 mars 2009 Statut Membre Dernière intervention 27 octobre 2016 11
Modifié par ezor le 31/08/2015 à 16:52
merci de ta réponse.
J'utilisais déjà Application.WorksheetFunction.Combin() mais j'ia une erreur 400 qui ressort avec ça. Je n'arrive pas à trouver à quoi elle correspond.
C'est pour cela que j'avais tenter de faire ma propre fonction au cas où.
0
ccm81 Messages postés 10851 Date d'inscription lundi 18 octobre 2010 Statut Membre Dernière intervention 16 avril 2024 2 404
31 août 2015 à 17:10
Idée 1. Récupères les valeurs dans des variables et regardes leur valeur lorsque ça plante
Idée 2. as tu bien n >= p
Idée 3. Cells(5, 4) = "18" si tu as laissé les guillemets, ça plante

Sinon, envoies la partie concernée de ton fichier via cjoint.com avec les exemples qui plantent

Cdlmnt
0
ezor Messages postés 176 Date d'inscription dimanche 1 mars 2009 Statut Membre Dernière intervention 27 octobre 2016 11
Modifié par ezor le 1/09/2015 à 09:54
dans le sens inverse ;) :
idée 3 : avec ou sans " " pas de changement
idée 2 : je n'ai pas l'impression que le problème vienne de là. J'ai un cas "if p>n" dans ma routine combinaison pour gérer ça
idée 1 : je vais tenter de faire ça, mais il y a beaucoup de variables, ça va me prendre du temps. Je te dis si jamais ça s'approche dangereusement de 9 223 372 036 854 775 807 (le maximum pour un Long!)

PS : 18! < max d'un Long
0
ezor Messages postés 176 Date d'inscription dimanche 1 mars 2009 Statut Membre Dernière intervention 27 octobre 2016 11
Modifié par ezor le 1/09/2015 à 11:28
Bon, pour une raison que j'ignore, j'ai une solution qui semble fonctionner même pour des nombres relativement grands. J'ai utilisé ma propre fonction "combinaison" avec pour le calcul des factorielles, Application.fact() ce qui donne le code suivant

'fonction combinaison
Public Function combinaison(ByVal p As Long, ByVal n As Long)

If p > n Then
combinaison = 0
Else
combinaison = Application.fact(n) / (Application.fact(p) * Application.fact(n - p))
End If

End Function


Je ne sais pas pourquoi c'est mieux ainsi. J'avais testé avec Application.combin(n,p) et en recodant la fonction factorielle par récursivité.
Je présume que le FACT() de excel est plus optimisé que le miens ou celui dans COMBIN()

Si quelqu'un à une explication je suis preneur.


EDIT : pour info, je peux aller jusqu'à "nombre de question restante" égale à 170 environ. Au dela, j'ai un message d'erreur "Incompatibilité de type". Ça doit dépasser la capactité d'un Long

ezor
0