## Forum archive 2000-2006

### John Jones - random bug?

by Arnold Pizer -
Number of replies: 0
 random bug? topic started 3/25/2003; 11:51:35 AMlast post 3/27/2003; 10:48:14 AM
 John Jones - random bug?  3/25/2003; 11:51:35 AM (reads: 1176, responses: 4) Hi, I was just shown a problem where the answer degenerated because  random(1, 4, 2) produced 5 for some students. The problem (result being bigger than $end) can show whenever  random($begin, $end,$incr) is called and $end-$begin is not a multiple of $incr. John <| Post or View Comments |>  Michael Gage - Re: random bug? 3/25/2003; 10:33:31 PM (reads: 1406, responses: 0) 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 |>  John Jones - Re: random bug? 3/27/2003; 12:32:52 AM (reads: 1377, responses: 0) Hi Mike, I took a mini survey of what people here thought random(a,b,c) should do in cases like this, and we both agreed that it should produce a number of the form x=a+c*k where k is an integer and a le x le b. I think that can be acheived in PGrandom by making the key line: $out = $begin +$incr* int( ($new_seed/($modulus))* ( int( ($end-$begin)/$incr) +1 ) ) ; Does this produce any unexpected behaviours? John <| Post or View Comments |>  Arnold K. Pizer - Re: random bug? 3/27/2003; 9:07:08 AM (reads: 1389, responses: 0) Hi,John's solution is equivalent to replacing the original$end by $end-mod($end-$begin,$incr) with an obvious meaning if $inc is not integral. This forces$end-$begin to be a multiple of$incr. For example replacing random(1,4,2) by random(1,3,2) or replacing random(1,4.1,.2) by random(1,4.0,.2). This is the behavior you want. Arnie <| Post or View Comments |>

 John Jones - Re: random bug?  3/27/2003; 10:48:14 AM (reads: 1361, responses: 0) Hi, OK, I uploaded the change. John <| Post or View Comments |>