Excel VBA: Implementing Box Muller, Zigurrat and Ratio of Uniforms Algorithm This is a very specific question mixing up stochastic knowledge and VBA skills. So very exciting!

I'm trying to compare several methods for generating standard, normally distributed numbers given a source of uniformly distributed random numbers. Therefore I'm implementing the Box Muller Algorithm, Ziggurat Algorithm and Ratio of Uniforms Algorithm. Every single implementation works great in terms of generating a clean standard, normally distribution. (checked by Shapiro-Wilk-Test).

What I want to find out: which is the quickest method?

Testing every single program with a total of 10^7 generated numbers these are the run times:

Box-Muller: 3,7 seconds
Ziggurat: 1,28 seconds
Ratio of Uniforms: 10,77 seconds

Actually I am very happy about those readings, because I didn't expect it to be that fast. Of course the run time of every single method also depends on my programming skills and VBA knowledge. 

My problem: after doing some research I found out that the Ratio of Uniforms Algorithm should be the quickest (about 3 to 4 times quicker than Box Muller). This information just leans on this stack:



I am curious if this is just a wrong claim of this user or (what I do expect more) if my code is not perfectly implemented. Therefore I'll post my code and hope someone could help me with my question, if my code is just not good enough or if the Ratio of Uniforms just doesn't work that quick as mentioned.

Sub RatioUniforms()

Dim x(10000000) As Double
Dim passing As Long
Dim amount As Long: amount = 10000000
Dim u1 As Double
Dim u2 As Double
Dim v2 As Double

    Do While passing &lt;= amount
        Do
            u1 = Rnd    'rnd= random number(0,1)
        Loop Until u1 &lt;&gt; 0  'u1 musn't become 0
        v2 = Rnd
        u2 = (2 * v2 - 1) * (2 * exp(-1)) ^ (1 / 2)
        If u1 ^ 2 &lt;= exp(-1 / 2 * u2 ^ 2 / u1 ^ 2) Then
            x(passing) = u2 / u1
            passing = passing + 1
        End If
    Loop

 End Sub


Thank you very much helping me on this topic. Maybe some of you have tried those algorithms in VBA or other languages and can help me with there experience about the run time? If you need something else to know about my other implementations just let me know. Have a great day!
There are a few optimizations that can be made to the code to speed it up, mainly to do with how some mathematical operations are performed in VBA. Not sure if I have it implemented 100% accurately so please review for accuracy. Also, I'm sure there are more optimizations to be had, but this is hopefully a starting point for further conversation. 

A lot of my changes may be PC specific. It may ultimately depend on your CPU and instruction set available. On my computer, this runs in about 2.5 seconds.

A list of changes:


I replaced all instances of raising something to a power of two, instead, I just multiplied the item by itself.
I pre-computed this part Sqr((2 * Exp(-1))) as it appears to always be the same, so it isn't calculated for each loop and put it into a constant.
I removed the variable v2, it wasn't really needed, you just needed to introduce Rnd in one more spot
General cleanup of the code, and renamed a few variables for clarity


Code

Sub RatioUniforms()
    Const NumberOfIterations        As Long = 10000000
    Const u2CalculationSecondHalf   As Double = 0.857763884960707 'Caching this part Sqr((2 * Exp(-1)))
    Dim Results(NumberOfIterations) As Double
    Dim PassCounter                 As Long
    Dim u1                          As Double 'Define a better name if possible
    Dim u2                          As Double 'Define a better name if possible
    Dim MyTimer                     As Double

    MyTimer = Timer
    Do While PassCounter &lt;= NumberOfIterations
        Do: u1 = Rnd: Loop Until u1 &gt; 0
        u2 = (2 * Rnd - 1) * u2CalculationSecondHalf

        If u1 * u1 &lt;= Exp(-1 / 2 * (u2 * u2) / (u1 * u1)) Then
            Results(PassCounter) = u2 / u1
            PassCounter = PassCounter + 1
        End If

    Loop
    Debug.Print "Process took: " &amp; Timer - MyTimer

 End Sub