Boostez vos compétences Excel avec notre communauté !
Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !
Je devrais quitter la discussion car vous la compliquez inutilement et vous y croyez encore vous-même, c'est le monde à l'envers.dégonfle le melon
j'ai ouvert ce topic , si la tournure ne te plait pas tu peux toujours zapper
Option Explicit
Sub testBorne()
Dim borne&, count&, i&, x&, itest&
borne = 50
For itest = 1 To 200
For i = 1 To 100
x = Int(Rnd * borne)
If x = 50 Then count = count + 1
Next
Next
MsgBox "avec 200 test, " & borne & " est sorti " & count & " fois sur " & 100 & " tirages"
End Sub
Sub testBorne2()
Dim borne&, count&, i&, x&, itest&
borne = 50
For itest = 1 To 200
For i = 1 To 100
x = Int(Rnd * (borne + 0.999999))
If x = 50 Then count = count + 1
Next
Next
MsgBox "avec 200 test, " & borne & " est sorti " & count & " fois sur " & 100 & " tirages"
End Sub
parce que c'est le nerf de la guerre tout simplement, un algo qui fait ce qu'on lui demande mais qui plombe l'uc c'est pas un bon algoBonjour à tous,
Si je peux me permettre le problème n'est pas tant sur VBA.Rnd et ses flows mais sur la boucle qui s'arrête à mi-parcours. C'est de là que vient le mauvais mélange. Sur 10 éléments ça ne se "voit pas" mais sur des arrays plus importantes c'est évident, cf. fichiers de BsAlv et test de Rheeem.
Je ne comprends pas pourquoi la discussion est centrée sur les milisecondes et non sur l'algoritmique en elle-meme.
Si je peux me permettre le problème n'est pas tant sur VBA.Rnd et ses flows mais sur la boucle qui s'arrête à mi-parcours. C'est de là que vient le mauvais mélange.
pivot = tl \ 2
For a = 1 To tl Step 2
b = Int(Rnd * pivot) * 2 + 2
...
pivot = tl \ 2
rd = Int(Rnd * pivot) + pivot
For j = 1 To pivot
a = (((j * 101 + rd) Mod pivot) * 2) + 1
b = ((j * 97) Mod pivot) * 2 + 2
memo = t(a, 1)
t(a, 1) = t(b, 1)
t(b, 1) = memo
Next
Salut,et surtout je le redis si la semie boucle vous génère un melange non uniforme(si tant est que l'on puisse exprimer cela comme ça)
ce n'est pas elle la responsable mais bien RND
Option Explicit
'==========================
' Déclarations API
'==========================
#If VBA7 Then
Private Declare PtrSafe Function CryptAcquireContext Lib "advapi32.dll" _
Alias "CryptAcquireContextA" (ByRef phProv As LongPtr, _
ByVal pszContainer As String, ByVal pszProvider As String, _
ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
Private Declare PtrSafe Function CryptGenRandom Lib "advapi32.dll" _
(ByVal hProv As LongPtr, ByVal dwLen As Long, ByRef pbBuffer As Byte) As Long
Private Declare PtrSafe Function CryptReleaseContext Lib "advapi32.dll" _
(ByVal hProv As LongPtr, ByVal dwFlags As Long) As Long
Private m_hProv As LongPtr
#Else
Private Declare Function CryptAcquireContext Lib "advapi32.dll" _
Alias "CryptAcquireContextA" (ByRef phProv As Long, _
ByVal pszContainer As String, ByVal pszProvider As String, _
ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptGenRandom Lib "advapi32.dll" _
(ByVal hProv As Long, ByVal dwLen As Long, ByRef pbBuffer As Byte) As Long
Private Declare Function CryptReleaseContext Lib "advapi32.dll" _
(ByVal hProv As Long, ByVal dwFlags As Long) As Long
Private m_hProv As Long
#End If
'==========================
' Initialisation / libération
'==========================
Public Sub CryptoInit()
If m_hProv <> 0 Then Exit Sub
' PROV_RSA_FULL = 1, CRYPT_VERIFYCONTEXT = &HF0000000
If CryptAcquireContext(m_hProv, vbNullString, vbNullString, 1, &HF0000000) = 0 Then
Err.Raise vbObjectError + 1, "CryptoInit", "CryptAcquireContext a échoué."
End If
End Sub
Public Sub CryptoFree() 'pas obligatoire (fait à la fermeture d'Excel)
If m_hProv <> 0 Then
CryptReleaseContext m_hProv, 0
m_hProv = 0
End If
End Sub
'==========================
' Générateurs
'==========================
Private Function CryptoRandom64() As Double
Dim b(7) As Byte
Dim d As Double
If m_hProv = 0 Then CryptoInit
CryptGenRandom m_hProv, 8, b(0)
d = b(0) _
+ b(1) * 256# _
+ b(2) * 65536# _
+ b(3) * 16777216# _
+ b(4) * 4294967296# _
+ b(5) * 1099511627776# _
+ b(6) * 281474976710656# _
+ b(7) * 7.20575940379279E+16
CryptoRandom64 = d
End Function
Public Function CryptoRnd() As Double
Dim r As Double
' 2^64 - 1 ≈ 1.84467440737096E+19
r = CryptoRandom64() / 1.84467440737096E+19
' Sécurité : ne jamais renvoyer exactement 1
If r >= 1# Then r = 0.999999999999999#
CryptoRnd = r
End Function
'==========================
' Shuffle Fisher–Yates
'==========================
Public Sub ShuffleArray(ByRef arr As Variant)
Dim i As Long, j As Long
Dim tmp As Variant
Dim lo As Long, hi As Long
lo = LBound(arr)
hi = UBound(arr)
For i = hi To lo + 1 Step -1
j = lo + Int(CryptoRnd() * (i - lo + 1))
tmp = arr(i)
arr(i) = arr(j)
arr(j) = tmp
Next i
End Sub
Public Sub TestShuffle()
Dim t
Dim i As Long
t = Array("A", "B", "C", "D", "E", "F")
ShuffleArray t
For i = LBound(t) To UBound(t)
Debug.Print t(i)
Next i
End Sub
Sub M_Fisher_Yates()
Dim Arr, N1 As Long, N2 As Long, i1 As Long, i2 As Long, SWAP
Dim Bench As New cBenchmark
Bench.Start 'start chrono
Randomize 'utiliser SEED
Bench.TrackByName "debut" 'premier jalon '
Arr = Range("Sample").Value2 'lire les données pour le tirage
N1 = LBound(Arr) 'lowerbound
N2 = UBound(Arr) 'upperbound
Bench.TrackByName "end READ" '2ième jalon
For i1 = N1 To N2 'boucler tous les éléments
i2 = Int(N1 + Rnd * (N2 - N1 + 1)) 'élément aléatoire
If i1 <> i2 Then 'échange nécessaire ?
SWAP = Arr(i2, 1) 'mémoriser cet élément
Arr(i2, 1) = Arr(i1, 1) 'échanger les 2
Arr(i1, 1) = SWAP 'coller l'élément en mémoire
End If
Next
Bench.TrackByName "fin Fisher_Yates" '3ième jalon
Range("Sample").offset(, 1).Value2 = Arr 'coller resultat juste à côté
DoEvents
Bench.TrackByName "fin WRITE" '4ième jalon
Bench.Report 'créer rapport
End Sub
la seule solution que j'ai pour l'instant c'est ma fonction perso RNDX qui travail avec une collection a la quelle je supprime la valeur sélectionné a chaque tour autrement il ne peut pas choisir la même valeur 2 fois mais on perd le gain de temps de la semie boucle je travail sur un pool /poolsize avec un tableau c'est prometteur en test pour l'instant
Function FYRnd(Optional ByVal InitMax As Long = 0) As Long
Static t() As Long
Static Count As Long
If InitMax > 0 Then
ReDim t(0 To InitMax)
Count = InitMax
Exit Function
ElseIf Count < 1 Then
Exit Function
End If
Dim NewV As Long, V As Long
NewV = Int(Count * Rnd + 1)
FYRnd = t(NewV)
If FYRnd = 0 Then: FYRnd = NewV
V = t(Count)
If V = 0 Then: V = Count
t(NewV) = V
Count = Count - 1
End Function
Sub TestFYRnd()
Dim nBr As Long, t, i As Long
nBr = 10000
FYRnd nBr 'initialization
ReDim t(1 To nBr, 1 To 1)
For i = 1 To nBr
t(i, 1) = FYRnd 'indices uniques
Next
Range("A1").Resize(nBr) = t
End Sub
We use cookies and similar technologies for the following purposes:
Est ce que vous acceptez les cookies et ces technologies?
We use cookies and similar technologies for the following purposes:
Est ce que vous acceptez les cookies et ces technologies?