Not being a graphics guy I have a limited imagination with regard the use of a normal distribution. Imagine pushing both ends of a uniform distribution such that the centre starts to lift and the ends start to drop. What we get is a bell shape - a normal distribution.
If we select a range with our uniform distribution then any value within that range will have, in theory, the same likelihood of being selected. However, with a normal distribution there will be bias toward the centre of the range with a lesser chance of the outliers been selected.
Imagine flying in a straight line, and we want a random shift in direction. With a uniform distribution a 10% shift to the left or right is just as likely as a 20% shift to the left or right. With a normal distribution most shifts will be within, say, ± 10% and a further shift to the left or right will be less likely. A shift of ± 60% may be close to impossible.
What I have described may be of no use to a graphics programmer but as intimated above what do I know?
I have added a Gauss function to NR32.bas. I have included it in earlier PRNGs of mine but never went into much detail about its use.
With a range of 5 to 15 we have a mean of 10 and that is what we use in our calculations. The bell shape will be like a fried egg for large standard deviations and a traffic cone for small standard deviations.
This is the formula to use:
value = Mean + (2*(Rnd<0.5)+1)*NR.Gauss*StandardDeviation
If Rnd <0.5 then we subtract from the mean else we add to the mean.
Here are two sets of figures: The first set is the return values from the continuous range function NR.Range(5.,15); the second set is from using the formula above. As you can see the uniform distribution has an even spread whereas the normal distribution sees the 80% likelehood range been compressed and the outliers are not getting a 'look in'. The standard deviation used in the above was 0.78.
Code: Select all
6.106326372828335 -> 80%
10.28502926230431 Mid range
14.19233973370865 -> 80%
8.31719026898374 ---> 95%
8.833664686882646 --> 90%
10.01657096269018 Mid range
10.98436492519554 -> 80%
11.24853922263923 --> 90%
11.45563230600347 ---> 95%
If this post has any potential for you than add to the opening post:
'Declare Function Gauss() As Double' in Type NR32
and add this
Code: Select all
Private Function NR32.Gauss As Double
Static As Long u2_cached
Static As double u1, u2, x1, x2, w
If u2_cached = -1 Then
u2_cached = 0
Function = u2
x1 = This.RandD
x2 = This.RandD
w = x1 * x1 + x2 * x2
Loop While w >= 1
w = Sqr( -2 * Log(w)/w )
u1 = x1 * w
u2 = x2 * w
u2_cached = -1
Function = u1
The code has been analysed and the theoretical values of 80%, 90%, 95%, and 99% were calculated as 80.02%, 89.98%, 94.99% and 99.02% so the code is doing a good job. That is not my code by the way and can found on the internet at many sites, for quite a few years now, so I don't know who the original author is. There is some tasty crunching going on there and the throughput on my machine is about 28.3MHz. This is slow compared with Rnd's equivalent but a single value comes in at about 35 nanoseconds, so you will not have the time to put the kettle on.