UDF Несоответствие типов генератора случайных чисел - PullRequest
0 голосов
/ 07 ноября 2018

Я почти час пытался обернуть голову вокруг этой проблемы, но, похоже, она ни к чему не привела.

По сути, я хотел попробовать лучший генератор случайных чисел и нашел этот код, который я хотел попробовать реализовать в моей программе

 Function RandNorm(Optional mean As Double = 0, _
              Optional Dev As Double = 1, _
              Optional Corr As Double = 0, _
              Optional bVolatile As Boolean = False) As Double()


Randomize
Dim z(0 To 1)   As Double
Dim U           As Double
Dim V           As Double
Dim S           As Double

If bVolatile Then Application.Volatile

Do
    U = 2 * [rand()] - 1
    V = 2 * [rand()] - 1
    S = U * U + V * V
Loop Until S < 1

S = Sqr(-2 * Log(S) / S)
z(0) = Dev * U * S + mean
z(1) = Dev * V * S + mean

If Corr <> 0 Then z(1) = Corr * z(0) + Sqr(1 - Corr ^ 2) * z(1)
RandNorm = z
End Function

Как видите, функция возвращает число. При запуске в Excel, как =RandNorm(), все в порядке. Но при запуске, например, такой простой код, как этот:

 Sub test()

    Dim x() As Double, i As Long

    ReDim x(1 To 10, 1 To 1)
    For i = 1 To 10
          x(i, 1) = RandNorm
    Next i

    Range("A1:A10") = x
End Sub

Это дает мне ошибку "Несоответствие типов", хотя она была определена As Double. Если я определю RandNorm As Double в Sub, это даст мне 0. Однако, если я заменю x(i, 1) на Cells(i, 1), это сработает.

Функция находится в своем собственном модуле и сабе тоже.

Что я пропустил? Любая помощь могла бы быть полезна. Заранее спасибо!

1 Ответ

0 голосов
/ 07 ноября 2018

Double не совпадает с Double(): RandNorm возвращает массив . При использовании в качестве UDF в отдельной ячейке, RandNorm возвращает первый элемент этого массива. Например, рассмотрим следующую функцию.

Function foo() As Double()
    Dim z(0 To 1) As Double
    z(0) = 1
    z(1) = 2
    foo = z
End Function

При использовании в качестве UDF в отдельной ячейке, =foo() всегда будет возвращать 1. Вам нужно будет ввести его в виде формулы массива в 2 ячейки с помощью Ctrl + Shift + Введите , чтобы отобразить второй элемент 2.

Простое исправление может измениться с Double() на Double и RandNorm = z на RandNorm = z(0).

Function RandNorm(Optional mean As Double = 0, _
              Optional Dev As Double = 1, _
              Optional Corr As Double = 0, _
              Optional bVolatile As Boolean = False) As Double
    ....
    If Corr <> 0 Then z(1) = Corr * z(0) + Sqr(1 - Corr ^ 2) * z(1)
    RandNorm = z(0)
End Function

Хотя трудно сказать, что это то, что вы ищете - поскольку вы фактически игнорируете z(1).

...