This recipe produces random numbers from a normal (bell-shaped) distribution. (The rand() command in Tcl produces uniformly distributed random numbers.)
| Tcl |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # The following procedure generates two independent normally distributed
# random numbers with mean 0 and vaviance stdDev^2. If you only need 1
# random number, choose either one.
proc randNormal {stdDev} {
global dRandNormal1
global dRandNormal2
set u1 rand()
set u2 rand()
set dRandNormal1 [expr $stdDev * sqrt(-2 * log($u1)) * cos(2 * 3.14159 * $u2)]
set dRandNormal2 [expr $stdDev * sqrt(-2 * log($u1)) * sin(2 * 3.14159 * $u2)]
}
# The following code is only used to demonstrate the procedure and should
# be replaced by your own code.
for {set i 1} {$i<10} {incr i} {
randNormal 1
puts $dRandNormal1
puts $dRandNormal2
}
|
Discussion
This recipe is useful when you need random numbers from a normal distribution, such as simulating measurement noise. This solution is a very simple, straightforward way to convert Tcl's uniformly distributed random numbers to normally distributed random numbers. If you want to use this for Monte Carlo simulation you should pre-process rand() as described at http://mini.net/tcl/1551


Comments
I am not sure why the commands
are there. Semantically they have no effect. The code in the recipe is equivalent to
Code Explanation. u1 and u2 need to be the same in both calculations, so I chose them up front. If you don't keep them the same, there is no guarantee that the normal random numbers will be independent.
Bill Kappele (bill@mathoptions.com)
Code Correction. Thank you, Andreas. The code should read
set u1 [expr rand()] set u2 [expr rand()]
to function correctly.
Need to be the same. Need a third variable to make both the same
set temp [expr rand()]
set u1 $temp
set u2 $temp
Two variables. I believe two variables are needed. I am not familiar with the current language you are using, but the variables in the formulas must be uncorrelated to provide gaussian like distribution. i.e.:
a = rand_0_1() ;
b = rand_0_1() ;
y1 = sigma * sqrt(-2.0 * a )*cos(2.0 * pi * b ) ;
y2 = sigma * sqrt(-2.0 * a )*sin(2.0 * pi * b ) ;
the random numbers y1 and y2 are now orthogonal and normally distributed. I think.
Sign in to comment