Abstract
Wenn Sie eine schrittweise kumulierte Verteilungsfunktion von Zufallszahlen erzeugen müssen, können Sie diese benutzerdefinierte Funktion sbRandCumulative verwenden. Falls Sie die Herleitung des Algorithmus interessiert, schauen Sie bitte auf die Seite für sbRandGeneral.
Appendix – Programmcode sbRandCumulative
Bitte den Haftungsausschluss im Impressum beachten.
Option Explicit
Function sbRandCumulative(dMin As Double, dMax As Double, _
vXi As Variant, vWi As Variant, Optional dRandom = 1#) As Double
'Generates a random number, Cumulative distributed.
'[see Vose: Risk Analysis, 2nd ed., p. 109]
'Source (EN): http://www.sulprobil.com/sbrandcumulative_en/
'Source (DE): http://www.bplumhoff.de/sbrandcumulative_de/
'(C) (P) by Bernd Plumhoff 23-Dec-2020 PB V0.50
'Similar to @RISK's (C) RiskCumulative function.
Static bRandomized As Boolean
Dim i As Long
Dim dA As Double
Dim dRand As Double
Dim dSgn As Double
If vWi.Count <> vXi.Count Then
sbRandCumulative = CVErr(xlErrValue)
Exit Function
End If
ReDim dX(0 To vXi.Count + 1) As Double
ReDim dW(0 To vWi.Count + 1) As Double
dX(0) = dMin
dX(UBound(dX)) = dMax
dW(0) = 0#
dW(UBound(dW)) = 1#
For i = 1 To vXi.Count
dX(i) = vXi(i)
dW(i) = vWi(i)
If dW(i) < dW(i - 1) Then
'Weights need to be monotonously increasing
sbRandCumulative = CVErr(xlErrValue)
Exit Function
End If
Next i
If dW(UBound(dW)) < dW(UBound(dW) - 1) Then
'Weights need to be monotonously increasing
sbRandCumulative = CVErr(xlErrValue)
Exit Function
End If
'Calculate area
dA = 0#
For i = 0 To UBound(dX) - 1
If dX(i) >= dX(i + 1) Or dW(i) < 0# Then
sbRandCumulative = CVErr(xlErrValue)
Exit Function
End If
dA = dA + (dX(i + 1) - dX(i)) * (dW(i + 1) + dW(i)) / 2#
Next i
'Normalise weights to set area to 1
For i = 1 To UBound(dW)
dW(i) = dW(i) / dA
Next i
ReDim dF(0 To UBound(dX)) As Double
'Calculate border points of value ranges for
'cumulative inverse function
dF(0) = 0#
dA = 0#
For i = 0 To UBound(dX) - 1
dA = dA + (dX(i + 1) - dX(i)) * (dW(i + 1) + dW(i)) / 2#
dF(i + 1) = dA
Next i
If dRandom = 1# Then
If Not bRandomized Then
Randomize
bRandomized = True
End If
dRand = Rnd()
Else
dRand = dRandom
End If
i = 1
Do While dF(i) <= dRand
i = i + 1
Loop
dSgn = Sgn(dW(i) - dW(i - 1))
If dSgn = 0# Then
sbRandCumulative = dX(i - 1) + (dRand - dF(i - 1)) / _
(dF(i) - dF(i - 1)) * (dX(i) - dX(i - 1))
Else
sbRandCumulative = dX(i - 1) + _
dSgn * Sqr((dRand - dF(i - 1)) * _
2# * (dX(i) - dX(i - 1)) / (dW(i) - dW(i - 1)) + _
(dW(i - 1) * (dX(i) - dX(i - 1)) / _
(dW(i) - dW(i - 1))) ^ 2#) - _
dW(i - 1) * (dX(i) - dX(i - 1)) / (dW(i) - dW(i - 1))
End If
End Function
Bitte den Haftungsausschluss im Impressum beachten.
sbRandCumulative.xlsm [50 KB Excel Datei, ohne jegliche Gewährleistung]