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.

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.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

Download

Bitte den Haftungsausschluss im Impressum beachten.

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