我正在尝试创建一个棒球季后赛模拟器,以了解糟糕的投手对球队的冠军赔率有多大影响。所以我基本上为季后赛创建了一个模拟器(3轮,第一轮是5局3胜,接下来的两轮是7局3胜)。我可以看到,如果 SP 每三场比赛就投球一次,并且他将获胜的机会减少 10%,那么他会对球队造成多大的伤害。
为了确保我写了这篇文章,我首先在没有任何调整的情况下运行模拟,这样每场比赛两支球队都有 50% 的获胜机会......(因此,一支球队有 12.5% 的机会赢得世界大赛) 3 轮季后赛)然而,我一直高于 12.5。
我感觉问题出在 Rnd 函数上,所以我玩了一下(添加了一个函数,尝试改变时间等),现在我的模拟结果是 <12.5%. I then tried to trouble shoot and noticed that in each round was not being won 50% of the time... which was the case each time I re-ran the simulation (Like round 1 would have a 47% success then round two 51% then round three 58%... then the next run would return 46%, 52%, 59%.
我做错了什么,还是这只是 rnd 函数不擅长处理的事情?
Public Function wRandomNumber(lowerbound, upperbound, Optional rndType = 1) As Double
Dim rndVariable As Double
'Const ms As Double = 0.000000011574
Randomize Timer
'Application.Wait Now + ms * 1
rndVariable = Rnd
If rndType = 1 Then
wRandomNumber = Int((upperbound - lowerbound + 1) * rndVariable + lowerbound)
ElseIf rndType = 2 Then
If (upperbound - lowerbound + 1) * rndVariable + lowerbound <= upperbound Then
wRandomNumber = (upperbound - lowerbound + 1) * rndVariable + lowerbound
Else
Do While (upperbound - lowerbound + 1) * rndVariable + lowerbound > upperbound
rndVariable = Rnd
If (upperbound - lowerbound + 1) * rndVariable + lowerbound <= upperbound Then
wRandomNumber = (upperbound - lowerbound + 1) * rndVariable + lowerbound
End If
Loop
End If
End If
End Function
Public Sub Playoff_sim()
Dim game_num As Integer
Dim lds_wins_stros As Integer
Dim lds_loss_stros As Integer
Dim lcs_wins_stros As Integer
Dim lcs_loss_stros As Integer
Dim ws_wins_stros As Integer
Dim ws_loss_stros As Integer
Dim p As Double
Dim outcome1 As Single
Dim outcome2 As Single
Dim outcome3 As Single
Dim i As Double
Dim iter As Double
Dim CHAMPS As Double
Dim Loser As Double
Dim p_bad As Double
Dim p_norm As Double
Dim lds_champs As Double
Dim lcs_champs As Double
Dim r As Double
Const ms As Double = 0.000000011574
iter = 100000
CHAMPS = 0
Loser = 0
lds_champs = 0
lcs_champs = 0
p_bad = 0.5
p_norm = 0.5
r = 0
For i = 1 To iter
game_num = 1
lds_wins_stros = 0
lds_loss_stros = 0
lcs_wins_stros = 0
lcs_loss_stros = 0
ws_loss_stros = 0
ws_wins_stros = 0
Do Until lds_wins_stros = 3 Or lds_loss_stros = 3
outcome1 = wRandomNumber(0, 1, 2)
If game_num = 3 Then
p = p_bad
Else
p = p_norm
End If
If p > outcome1 Then
lds_wins_stros = lds_wins_stros + 1
Else
lds_loss_stros = lds_loss_stros + 1
End If
r = r + 1
'Worksheets("Playoff_Sim").Cells(r, 15).Value = outcome1
game_num = game_num + 1
Loop
If lds_wins_stros = 3 Then
outcome2 = wRandomNumber(0, 1, 2)
lds_champs = 1 + lds_champs
Do Until lcs_wins_stros = 4 Or lcs_loss_stros = 4
If game_num = 3 Or 6 Or 9 Or 12 Or 15 Or 18 Or 21 Then
p = p_bad
Else
p = p_norm
End If
If p > outcome2 Then
lcs_wins_stros = lcs_wins_stros + 1
Else
lcs_loss_stros = lcs_loss_stros + 1
End If
game_num = game_num + 1
Loop
If lcs_wins_stros = 4 Then
lcs_champs = lcs_champs + 1
outcome3 = wRandomNumber(0, 1, 2)
Do Until ws_wins_stros = 4 Or ws_loss_stros = 4
If game_num = 3 Or 6 Or 9 Or 12 Or 15 Or 18 Or 21 Then
p = p_bad
Else
p = p_norm
End If
If p > outcome3 Then
ws_wins_stros = ws_wins_stros + 1
Else
ws_loss_stros = ws_loss_stros + 1
End If
'r = r + 1
game_num = game_num + 1
'Worksheets("Playoff_Sim").Cells(r, 15).Value = outcome3
Loop
If ws_wins_stros = 4 Then
CHAMPS = CHAMPS + 1
Else
Loser = Loser + 1
End If
Else
Loser = Loser + 1
End If
Else
Loser = Loser + 1
End If
Next i
Worksheets("Playoff_Sim").Cells(2, 1).Value = CHAMPS
Worksheets("Playoff_Sim").Cells(2, 2).Value = Loser
Worksheets("Playoff_Sim").Cells(2, 3).Value = lds_champs
Worksheets("Playoff_Sim").Cells(2, 4).Value = lcs_champs
结束子
问题不仅在于随机数(可以通过@A.S.H的建议使用
Application.RandBetween
来解决),还在于模拟的逻辑。重复两次的代码片段
If game_num = 3 Or 6 Or 9 Or 12 Or 15 Or 18 Or 21 Then
p = p_bad
Else
p = p_norm
End If
相当于单行
p = p_bad
。这是因为条件 game_num = 3 Or 6 Or 9 Or 12 Or 15 Or 18 Or 21
始终评估为 True
,因为您仅将 game_num
与 3
进行比较,然后强制 VBA 将剩余数字 (6,9,15,18,21) 解释为 True
通过与它们一起使用 Or
运算符。相反,只需这样做:
If game_num Mod 3 = 0 Then
p = p_bad
Else
p = p_norm
End If
可能还有其他问题,但这应该足以让您开始。
我一直在探索随机数生成器,我注意到频繁重新随机化(我认为这就是随机计时器在这里所做的)实际上是有害的。
我一直在做一个简单的:
随机化
如果rnd
代码,随机化使数字偏向较低的值,使用此代码,我的测试成功率为 15%,统计上应该有 5% 的成功率。
我对模拟器进行了很多次运行,事实上,比我想要的还要多,因为这样的结果分布得更好,然后不断地重新随机化。