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

` 5.238640960305929`

5.26641181204468

5.441864607855678

6.106326372828335 -> 80%

6.292966627515853

6.482123399619013

6.655931118875742

7.360141410026699

8.295693520922214

8.331588364671916

8.417925206013024

8.784137177281082

8.812430566176772

9.314218556974083

9.483385249041021

10.28502926230431 Mid range

10.50174724077806

10.69351680343971

11.2051329552196

11.58046164782718

11.61859277635813

12.0042270142585

12.04707070020959

12.28911123471335

12.63634555274621

12.71794609259814

13.18663582671434

13.34884512005374

13.69387058075517

14.19233973370865 -> 80%

8.31719026898374 ---> 95%

8.833664686882646 --> 90%

8.905205663371172

8.984731259750831

9.050552101154359 ->80%

9.188419748145686

9.332126853577261

9.409778093683855

9.594137369002333

9.631111012712989

9.664445172313828

9.670158637957487

9.746191647407478

9.865339639275383

10.01657096269018 Mid range

10.08065028515455

10.28862745559271

10.32506790230842

10.50106504428896

10.59733841359473

10.62891671569422

10.63338804672681

10.91634128687909

10.9525009090197

10.98436492519554 -> 80%

11.05649461343446

11.24853922263923 --> 90%

11.32543199443827

11.45563230600347 ---> 95%

11.8251349878606

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

Else

Do

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

End If

End Function

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.