PDA

View Full Version : How random is "RANDOM"?



RussMartin
- 12th June 2008, 23:00
I'd like to get a better feeling for how random the result from RANDOM is. Any comments?

tenaja
- 12th June 2008, 23:38
IIRC, it repeats every 65,000 times.

skimask
- 13th June 2008, 00:52
IIRC, it repeats every 65,000 times.

IF you use the same seed value every time, yes, it repeats the same sequence every 65535 time.
However, whenever I'm using RANDOM, I use a whatever 16-bit I have free as the seed value. That works as long as I'm not grabbing the 16-bit timer value at the same exact time every time.

mister_e
- 13th June 2008, 01:04
http://www.picbasic.co.uk/forum/showthread.php?t=7555&

If you want something really random... white noise generator fed to an internal PIC counter + using a random sampling time... even the white noise generator with Count would probably do.

Tons of way to Fry and egg
Tons of way to Skin a Cat
Every road leads to Roma

Choose the one who fits your local expression :D

RussMartin
- 13th June 2008, 16:15
I guess my question was a little broad. Let me refine it.

For example, were I to generate random intervals between 1 and 10 seconds long (inclusive) doing this:



SEED=32771
LOOP: RANDOM SEED
TIME=(SEED//10)+1
TIME=1000*TIME
HIGH LED
PAUSE TIME
LOW LED
PAUSE 1000
GOTO LOOP
END


. . . can I expect the distributions to "look" really random? (In 100 loops, can I expect to see about 10 of each value in each category of 1 second, 2 seconds . . . 10 seconds, etc.?) And, in the sequence, will I see a discernable pattern?

In some small BASIC implementations, I've had to do the equivalent of this:




SEED=32771
LOOP: RANDOM SEED
TIME=(SEED//11)+1
IF TIME<2 OR TIME>10 THEN GOTO LOOP
TIME=1000*TIME
HIGH LED
PAUSE TIME
LOW LED
PAUSE 1000
GOTO LOOP
END


. . . in order to get good distributions of small numbers.

mister_e
- 13th June 2008, 18:12
Probably you'll have better results if you change the SEED value.

BrianT
- 15th June 2008, 23:37
I found the RANDOM function to be pretty good for number distribution. I can't find it now but I had PBP generate groups (up to thousands) of numbers in the range I needed. I captured these a comma delimited file that I opened in Excel and looked at the distribution. It was plenty good enough for what I wanted but would not satisfy the lotteries commission.

If the system has a human operator, I start with a randomised seed as follows:-

Button is to ground with a resistor pullup to +5V



Pseudocode
Pushbutton var portb.0
w var word
lcdout $FE, $01, "Press button to start"

GetSeed:
random w
if pushbutton = 0 then SeedFound
goto getseed

SeedFound:
lcdout $FE, $01, "Seed = ", #W


W is now a random number between 1 and 65535. 0 is never produced. You need to scale this to the range you are interested in either by division as you are doing or by repeating the random instruction until a value that falls in your range is produced. The system is defeated if the user holds the button down before powering up. Needs a check for that.

This approach relies on a human operator seeing the LCD instruction then pushing the button to stop the counter. Due to reflex times, etc, it generates a pretty good random number.

If the system has no human to press the button, I have used a fast loop between turn on and the next positive going zero crossing of the mains. This needs an opto or similar way of finding the zero crossing.

The only better way that I know of is to use a white noise generator.

Your second code example I think has a problem. I don't think it will ever produce 0 or 1 since it returns to LOOP if time < 2. The random//11 function returns values 0 to 10 so the test for TIME > 10 is never true.


HTH
BrianT

RussMartin
- 16th June 2008, 01:02
You're right, Brian--I was coding from memory and left out an expression in the fifth line:



SEED=32771
LOOP: RANDOM SEED
TIME=(SEED//11)+1
IF TIME<2 OR TIME>10 THEN GOTO LOOP
TIME=1000*(TIME-1)
HIGH LED
PAUSE TIME
LOW LED
PAUSE 1000
GOTO LOOP
END


That will generate the values 1 to 10.

I've had to use a similar trick before with other forms of BASIC, notably a tinyBASIC implementation for the 8051 family, because the "ends" of the range (1 and 10) came up disproportionately often.

If you were satisfied with the distribution based on your empirical test, then it's certainly good enough for any applications I have in mind.

Thanks for a really good answer!

sayzer
- 16th June 2008, 11:23
Another way of getting a really truly actually indeed working random value and FOR SURE the number you get is always different each time;

Have the Timer1 running in the background continuously;

If you need a 16-bit random value, read TMR1L and TMR1H.

If you need 8-bit value, just read TMR1L.


Good ? Bad ?


:)

-----------------

skimask
- 16th June 2008, 14:15
Good ? Bad ?
See Post #3... It's always worked for me.

BrianT
- 17th June 2008, 00:35
Simply reading TMR0 or TMR1 is NO guarantee of a random seed.

In some systems where the code runs for days and takes innumerable branches and folds it might be pretty good but in other systems the code trajectory is the same every time the code is run. In that case TMR0 and TMR1 will always yield the same values.

You MUST introduce something truly indeterminate, such as a noise source or an unpredictable delay such as a human operator where response times will vary every time the operator pushes the button.

BrianT

skimask
- 17th June 2008, 02:04
Simply reading TMR0 or TMR1 is NO guarantee of a random seed.
Agreed 100%...but...if running on an internal oscillator, it could vary with temperature, perhaps far enough to mess with the seed enough. After all, theoretically, it only takes a single bit difference to change the order of things completely...theoretically that is :)
And exact temperature, therefore precise oscillator speed, is truly indeterminate, if, as you say, you have an external event trigger that is nonperiodic (aperiodic? anti-periodic? periodic-less?)