While emulating dice rolls with the Rnd
function I noticed some of the outcomes were more frequent than they were supposed to be.
Example code:
' Note, depending on computer speed this procedure may take about a minute to run
Sub sim3()
Dim intFirst As Integer, intSecond As Integer, intDie1 As Integer, intDie2 As Integer
Dim i As Long, j As Long, lngCount As Long, lngExpected As Long, lngLowerCount As Long, lngIterations As Long
lngIterations = 1000000
' select dice roll
intDie1 = 1 ' any number between 1 and 6
intDie2 = 3 ' any number between 1 and 6
' expected frequency
' (= 55,555 if lngIterations = 1,000,000 and intDie1 <> intDie2, = 27777 if lngIterations = 1,000,000 and intDie1 = intDie2)
If intDie1 = intDie2 Then lngExpected = Int((1 / 36) * CDbl(lngIterations)) Else _
lngExpected = Int((2 / 36) * CDbl(lngIterations))
For i = 1 To 100
lngCount = 0
For j = 1 To lngIterations
If j Mod 10000 = 0 Then DoEvents ' outcomment for faster execution
intFirst = randomDie
intSecond = randomDie
' count occurences of specific outcomes
If intFirst = intDie1 And intSecond = intDie2 Then ' 1,4
lngCount = lngCount + 1
ElseIf intFirst = intDie2 And intSecond = intDie1 Then ' 4, 1
lngCount = lngCount + 1
End If
Next j
If lngCount < lngExpected Then lngLowerCount = lngLowerCount + 1
Debug.Print i & ": #favourable outcomes: " & lngCount ' outcomment for faster execution
Next i
Debug.Print "(" & intDie1 & "," & intDie2 & ") #expected favourable outcomes per iteration (int.): " & lngExpected
Debug.Print "(" & intDie1 & "," & intDie2 & ") #iterations with lower than expected number of favourable outcomes: " & lngLowerCount
Debug.Print "(" & intDie1 & "," & intDie2 & ") Prob. of obtaining result or lower, F(x|n,p) : " & WorksheetFunction.Binom_Dist(lngLowerCount, i, 0.5, True)
End Sub
The randomDie
function used in the procedure is standard code for generating an integer between 1 and 6 (source):
Function randomDie() As Integer
Randomize
randomDie = Int((6 * Rnd) + 1)
End Function
Notice the Randomize
statement which shifts the seed number of VBA's PRNG algorithm each time the function is called which means the results of the sim3
procedure are not the same each time it is executed.
The results for the 21 combos of dice rolls along with the probability of obtaining that or a lower result:
We would expect the results of the favourable outcomes to be about evenly distributed around the mean (μ = 50, i=100
), but these results are absolutely extreme.
Are there flaws in my code, is my computer the problem or is the VBA PRNG biased?