Abstract

Wenn Sie eine schrittweise kumulierte Verteilungsfunktion von Zufallszahlen erzeugen müssen, können Sie diese benutzerdefinierte Funktion sbRandCumulative verwenden. Die Herleitung des Algorithmus ist analog zu sbRandGeneral.

sbRandCumulative

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.de/sbrandcumulative_en/
'Source (DE): http://www.berndplumhoff.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

Download

Bitte den Haftungsausschluss im Impressum beachten.

sbRandCumulative.xlsm [48 KB Excel Datei, ohne jegliche Gewährleistung]