random function to choose a number 1 thru 6

charles_platt

New member
For a game, I am thinking I can get an evenly weighted random integer from 1 through 6 by doing this:

--use the byte value from the random function.
--if 252 or greater, discard and get another random byte.
--divide by 6 using modulus // operator and assign the result to a variable.
--add 1

Is there a more elegant way to do it? I would prefer to have every result taking an equal amount of processor time, so throwing away numbers =>252 and trying again is not optimal.
 

AllyCat

Senior Member
Hi,

You MUST use a Word value for the RANDOM function or it will give very non-random results ! Also it NEVER generates a zero value, so the exactly equal odds are on the numbers between 1 and 65535. Note that PICaxe ALWAYS starts with the same sequence from its default RAM values (zeros) , so for a program that always starts "differently", the simplest solution is READ : INCrement : WRITE the Word value (to the EEPROM) each time the program starts. But for that to work, you also need to use a #NO_DATA at the start of the program, to prevent the DATA/EEPROM being "updated".

The simplest calculation (for a range of 1 - 6) is RANDOM w0 : Rollbyte = w0 // 6 + 1 which will take an almost constant time, whatever the value. That gives a very slight bias (of less than 1 in 10,000 or 0.01%) on the values 1 , 2 and 3 (I believe), which is probably the best that can be done when using the PICaxe RANDOM function.

If you're interested in the "Technicalities", most are explained in my Code Snippet HERE. Interestingly, RANDOM is almost the fastest PICaxe instruction (similar to a LOW/HIGH <pin> ), significantly faster than the DIVIDE//MODULUS or a READADC, which are alternative ways to introduce some more "Randomness" into the program. ;)

Cheers, Alan.
 

erco

Senior Member
If there is a pushbutton to generate the random number, time the keypress duration with a fast clock. That's plenty random already, and if desired use that with RANDOM in a calculation.
 

hippy

Technical Support
Staff member
Randomness is quite a complicated subject and I am no expert. The main problem, apart from predictability of the next number in sequence, is, with 16-bit random numbers which the PICAXE supports, value 0 to 65535, that's not exactly divisible by six so there's always going to be some distribution bias. Such bias is likely to persist no matter how one slices and dices that. to get a smaller random range.

As AllyCat notes the bias is fairly low so can likely be discounted in most cases.

I have tended to favour dividing a 16-bit random number by some prime number, then a modulo of 6 and adding one to give a 1 to 6 result -
Code:
Random w0                 ; w0 => b1:b0
b2 = w0 / 17 // 6 + 1
I have never analysed that for bias because that has delivered random-enough results for me when I have required them.

Also, somewhat ironically, my attempts to generate a random sequence have often involved countering true randomness, because getting the same number in succession just doesn't feel right in some applications, particularly for "what track to play next" in a music application.

I have tended to call routines such as -
Code:
GetRandomNumberOneToSix:
  bLast = bRandomOneToSix
  Do
    Random wRandomWord
    bRandomOneToSix = wRandomWord / 17 // 6 + 1
  Loop While bRandomOneToSix = bLast
  Return
Unless there are good reasons to need deterministic timing I wouldn't personally worry too much about code sometimes taking longer than other times.
 
Top