AmirAbbas
AmirAbbas

Reputation: 11

generating random number with normal distribution in VBA- Runtime error ‘1004’

I have problem with generating random numbers with normal distribution in VBA. I’m working on NSGAII. I use “Application.WorksheetFunction.Norm_Inv (Rnd, Mean, Deviation)” to generate random numbers with normal distribution. But I this error raises:

Runtime error ‘1004’: Unable to get the Norm_Inv property of the worksheetfunction class

How can I fix this error?

I’ve already used this code in another simple macro and it works. But by using this code in NSGAII code there is an error! (Large number of variables (double, long, Boolean, etc.) and 2D arrays are defined and used in NSGAII code and it consist of some do while, for, etc. loops)

I used break point at line "Function GenerateNormRand() As Double". when I break and continue (run code step by step), there is No Any Error! But when I don't, error raises.

Option Explicit
Function Mutation () As Variant
    .
    .
    .
    Dim RandomNumber As Double
    RandomNumber = GenerateNormRand ()
    .
    .
    .
End Function

Function GenerateNormRand () as double
    Dim myrand As Double
    randomize
    myrand = Application.WorksheetFunction.Norm_Inv(Rnd, 0, 5)
    GenerateNormRand = myrand
End Function

Even with explicit declaration of Double on every input and output variable the line GenerateNormRand = Application.WorksheetFunction.Norm_Inv ... raises runtime error 1004:

Sub TestThisFunction()
    MsgBox GenerateNormRand
End Sub

Function GenerateNormRand() As Double
    Randomize
    GenerateNormRand = Application.WorksheetFunction.Norm_Inv( _
        CDbl(Rnd), CDbl(0), CDbl(5))
End Function

Upvotes: 1

Views: 8989

Answers (1)

John Coleman
John Coleman

Reputation: 51998

Your problem description seems mysterious, but if you want to bypass the worksheet function, you could use the Box-Muller transform to generate your own normal random variables in pure VBA:

Function RandNorm(Optional mean As Double = 0, Optional sd As Double = 1) As Double
    Dim r1 As Double, r2 As Double, s As Double
    r1 = Rnd()
    If r1 = 0 Then r1 = Rnd() 'no danger of two zeros in a row in rnd()
    r2 = Rnd()
    s = Sqr(-2 * Log(r1)) * Cos(6.283185307 * r2) '6.28 etc. is 2*pi
    RandNorm = mean + sd * s
End Function

Upvotes: 2

Related Questions