This is a good point, but I'm not sure whether to try to fix this 'bug'
in the code or in the documentation. (i.e. what do you really expect to happen if increment doesn't divide the interval evenly.)
The code for all of this is in PGrandom.pm and is very short, so you
are invited to read it for yourself. The aim is to provide an easy
machine independent pseudo-random number generator, NOT to provide a
generator with a high degree of "randomness".
The essential formula is the following:
random(begin,end,inc) = inc * int( frac * ( (end - begin)/inc + 1 ) )
frac is between 0 and (2**32 -1)/(2**32)
The rightmost factor can also be written as (end - begin + inc) /inc
which is the number of partial intervals of length inc between begin
and end plus 1.
When inc divides the long interval evenly this is pretty clearly what
you want: random(0,1,1) should give you 0 and 1 with equal frequency
so we wish to pick a point on the line between 0 and 2 and take the
least integer. There might be a little edge effect which makes 0 very
slightly more likely than 2, but otherwise this is pretty good.
random(0,1.1,1) will pick a point on a line from 0 to 2.1 so you will
get numbers 0 and 1 and occasionally a 2 (which is causing the problem).
One possible variation on this would be to use
int( (end-begin +inc)/inc )
which would pick a point between 0 and 2 and give equal numbers of 0
and 1. In this case random(0, 1.1, 1) and random(0,1,1) would behave
identically.
random(0,1,0.2) picks a point in the interval 0 to 6 and then takes
least integer, so we have results 0,1,2,3,4,5 with equal frequency.
This is multiplied by 0.2 to give 0,.2,.4,.6,.8 and 1.0 with equal
frequency.
random(0,1.1, 0.2) picks a point in the interval 0 to 6.5 giving
0,1,2,3,4,5,6 with slightly unequal frequencies and then converts them
to 0 to 1.2 with unequal weights.
It looks like using
int( (end-begin +inc)/inc )
would again make random(0,1.1,0.2) behave exactly like (0,1,0.2)
which would be superior behavior -- although perhaps not what one
expected since 1.1 would never be obtained.
Does this seem right to the rest of you? These off-by-one cases can be
a bit tricky, and I'm not sure I've thought of all relevant cases.
Thanks for bringing this to our (collective) attention.
Take care,
Mike
<| Post or View Comments |>
|