Bonjour,
Je reviens sur ce sujet fermé en espérant le boucler définitivement.
Squenson a bien décrit le problème, mais son esquisse de solution n'est pas bonne.
Ma nouvelle méthode est très proche :
- Je détermine un tableau des valeurs possibles
- Je choisis au hasard un index dans le tableau.
- Je note la valeur pour cet index et je l'enleve de la liste. Plutôt que de retasser le tableau, je copie à l'index obtenu la valeur qui se trouve à l'index maximal.
- Je décrémente l'index maximal
- Je recommence au pas 2 en choisissant au hasard dans le tableau plus petit.
Ce qui nous donne, avec quelques améliorations de de détail :
Code : Tout sélectionner
'Renvoie un tableau aléatoire sans répétitions de <nbrTirages> entiers de 1 à <GammeValeurs>
'Le tableau commence à l'indice 1 et bien sûr nbrTirages ne peut être supérieur à GammeValeurs
Function Combinaison(GammeValeurs As Integer, nbrTirages As Integer)
Dim res(1 To nbrTirages) As Double
Dim valeurs(1 to GammeValeurs) As Integer
Dim i As Long, v As Long, valMax As Integer
' garde-fou
if (nbrTirages > GammeValeurs) or (nbrTirages < 0) or (GammeValeurs < 0) then err = 14
for i = 1 to GammeValeurs
valeurs(i) = i
next
valMax = GammeValeurs
for i = 1 to nbrTirages
' à chaque tour on puise dans la liste des valeurs restantes
do
v = 1 +Int(Rnd*valMax)
loop until v <= valMax ' contournement de bogue RND()
res(i) = valeurs(v)
valeurs(v) = valeurs(valMax)
valMax = valMax -1
next
Combinaison=res
End Function
Le nombre d'appels à RND est égal au nombre de tirages (sauf cas très rare de bogue de RND).
Pour Combinaison(70,70) la durée est toujours <= 16 ticks (16ms). Cependant, l'erreur 522 arrive encore, sur une répétition automatique. Voyons pourquoi.
Voici une version bidon de la fonction Combinaison, qui dure 1 seconde:
Code : Tout sélectionner
Function Combinaison(GammeValeurs As Integer, nbrTirages As Integer)
Dim res(1 To nbrTirages) As Double
wait 1000
Combinaison=res
End Function
Bien sûr avec un seul Ctrl-Maj-F9 le résultat sera tout à zéro.
Mais si on répète Ctrl-Maj-F9 avant une seconde, on obtient : err 522.
Ce qui veut dire que si l'appel de la fonction est renouvelé avant la fin d'exécution, Basic suppose une erreur de référence circulaire. Je pense que c'est une protection mise en place par Calc.