I'd like to get a better feeling for how random the result from RANDOM is. Any comments?
I'd like to get a better feeling for how random the result from RANDOM is. Any comments?
Russ
N0EVC, xWB6ONT, xWN6ONT
"Easy to use" is easy to say.
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.
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![]()
Steve
It's not a bug, it's a random feature.
There's no problem, only learning opportunities.
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:
. . . 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?Code:SEED=32771 LOOP: RANDOM SEED TIME=(SEED//10)+1 TIME=1000*TIME HIGH LED PAUSE TIME LOW LED PAUSE 1000 GOTO LOOP END
In some small BASIC implementations, I've had to do the equivalent of this:
. . . in order to get good distributions of small numbers.Code: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
Russ
N0EVC, xWB6ONT, xWN6ONT
"Easy to use" is easy to say.
Probably you'll have better results if you change the SEED value.
Steve
It's not a bug, it's a random feature.
There's no problem, only learning opportunities.
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
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.Code: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
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
Last edited by BrianT; - 15th June 2008 at 23:53. Reason: clarity
You're right, Brian--I was coding from memory and left out an expression in the fifth line:
That will generate the values 1 to 10.Code: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
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!
Russ
N0EVC, xWB6ONT, xWN6ONT
"Easy to use" is easy to say.
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 ?
-----------------
Last edited by sayzer; - 16th June 2008 at 12:01. Reason: typo
"If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte
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
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?)
Bookmarks