Random Numbers

hippy

Technical Support
Staff member
#1
Always use a word variable with the RANDOM command. If a byte variable is used the sequence of different numbers returned by RANDOM is very limited. Be careful not to use the variable used in the RANDOM command elsewhere in your code; writing to it will disturb the random sequence.

To calculate a random number between zero and N-1 use ...

-- RANDOM w0
-- w1 = w0 // N

To calculate a random number between 1 and N use ...

-- RANDOM w0
-- w1 = w0 // N + 1

So to determine a random dice roll of between 1 and 6 ...

-- RANDOM w0
-- w1 = w0 // 6 + 1

The // operator is 'modulus'. It returns the remainder after a division by the following number. So if 'w0' happened to be 9, 9 // 6 = 3, add 1 and we would have rolled a 4, which will be placed in the 'w1' variable.

The result variable ( 'w1' in examples above ) does not have to be a word variable, but can also be a byte variable if the number is less than 256 ...

-- RANDOM w0
-- b2 = w0 // 6 + 1

Note we cannot use 'b0' or 'b1' because they are part of 'w0' and this would alter 'w0' and mess up the random sequence.

Sometimes the random numbers are just not random enough. There are two solutions, firstly to divide down the random number before applying the modulus, and secondly to check that the random number generated is not the same as the last one. Both mechanisms can be used together ...

-- DO
---- RANDOM w0
---- b2 = w0 / 199 // 6 + 1
-- LOOP UNTIL b2 <> b3
-- b3 = b2

It can take a bit of experimenting to find the best value to divide by ( 199 in the above example - chosen for no particular reason ), and it is a good idea to write a short program which displays the numbers generated using SEROUT or SERTXD so you can check the numbers look okay for use, and the divisor can be adjusted appropriately.
 
Last edited:
#2
Useful and practical information, thanks. I've read several good articles, columns and one good book over the years that dug deeply into random number creation, actually in this picaxe case one should call it a pseudo-random number function.

Basically it is very difficult to create GOOD Quality random numbers with software alone. Many applications don't require high quality random numbers, but say, a state run lottery, would probably spend much time and money having to create and validate that the random generator was of such a quality to not disadvantage anyone.

It's one of those subjects that when explored will amaze one on the amount of research both academically and commercially that has gone and continues to go on around it. Having been exposed to crypto equipment in the military I was introduced to the subject at a younger age and still have a interest in it.

Hardware noise generators can be made into pretty good quality random number generators. A cool Picaxe project might be making a dedicated hardware based pseudo-random generator (say interfacing to a zener noise diode) that could function as a source of random numbers for higher level systems.

Lefty
 
#3
The PICAXE manuals suggest, at least for the X1 and X2 parts, using the timer function in order to seed the random number generator.

One caveat I have found, however, is that one must be careful of the count rate of the timer! For example, if the timer is set (via "SETTIMER preload" command) to count at one second intervals, and the program seeds RANDOM with the timer value multiple times within one second, the returns aren't random at all!

To overcome this in programs for which the timer is not needed for actual time, the count rate can be set to very fast, ensuring that a different seed value is used each time.

sdc
 
#4
Random uses the previous value to create the next one so if you use W0 then W0 (B0 and B1) can't be used elsewhere in the program (unless you peek and poke the values to store them temporarily). Also the seed starts off near zero so the first few values will have the high byte B1 at 0 for a while.

Nerd chat-up line: "Can I have your phone number to use as a seed for my random number generator?"
 
#5
A year or two ago I had the 08M spit out sequential random number values as binary to the terminal. I was curious as to why b1 showed zero for the first few inputs when the seed was 0. After watching the output for a while, I discovered that each random number in sequence was twice that of the seed value with a one added some of the time. Watching the bits, they were shifted left and a one or zero appended became the low bit in a pattern that walks through all the possible values.
 

hippy

Technical Support
Staff member
#6
A late addition to this thread - redpawn is right; this is a traditional way of doing 'Pseudo Random Number Generation' (PRNG) also known as using a 'Linear Feedback Shift Register" (LFSR).

A register holding the current number is shifted left and the new lsb is set 0 or 1 depending on the settings of other bits ( or shift right and set msb ). Each new 'random number' can be predicted from its previous and is ( for shift left ) twice the previous or twice the previous plus one.

While the sequence is predictable, and every new number relates to its previous, the order of numbers is not sequential hence 'pseudo random'.
 
#7
The Problem is that Nyquist... was there first, any Good Noise Source would simply be quite regularized by the sampling algorithm...
although a Zener Diode or an Avalanching pn junction is the best source of randomness next better is Cosmic Noise.
Robert K. Johnson Sr.
 
#9
So is there a way that i can use the random code to pick a number between 1 and 10 and then if a code name has that number it would run it? btw sorry if this sounds confusing... and if anyone can show me how to do that i would appreciate it so much heart emoticon

for example:

Main:
random 1-10 --- this here will pick number between 1-10

if random = 1 run 1 --- This will run Pin 1
if random = 2 run 2 --- This will run Pin 2
if random = 3 run 3 --- This will run Pin 3
if random = 4 run 4 --- This will run Pin 4
if random = 5 run 5 --- This will run Pin 5
if random = 6 run 6 --- This will run Pin 6
if random = 7 run 7 --- This will run Pin 7
if random = 8 run 8 --- This will run Pin 8
if random = 9 run 9 --- This will run Pin 9
if random = 10 run 10 --- This will run Pin 10

1:
High 1
pause 100
Low 1

2:
High 2
pause 100
Low 2

3:
High 3
pause 100
Low 3

4:
High 4
pause 100
Low 4

5:
High 5
pause 100
Low 5

6:
High 6
pause 100
Low 6

7:
High 7
pause 100
Low 7

8:
High 8
pause 100
Low 8
9:
High 9
pause 100
Low 9
10:
High 10
pause 100
Low 10
 

hippy

Technical Support
Staff member
#10
Welcome to the PICAXE forum.

You can use the following code to get a number of value between 1 and 10 ...

Code:
Random w0
w1 = w0 // 10 + 1
And then you can use a SELECT-CASE command to handle what to do depending on the number ...

Code:
Select Case w1
  Case 1
    High 1
    Pause 100
    Low 1
  Case 2
    High 2
    Pause 100
    Low 2
  Case ...
    ... etc
End Select
What you are setting HIGH or LOW needs to be a pin number or port.pin identifier so what to use for those numbers would depend on which PICAXE you were using and how your hardware was wired-up.
 
#11
Welcome to the PICAXE forum.

You can use the following code to get a number of value between 1 and 10 ...

Code:
Random w0
w1 = w0 // 10 + 1
And then you can use a SELECT-CASE command to handle what to do depending on the number ...

Code:
Select Case w1
  Case 1
    High 1
    Pause 100
    Low 1
  Case 2
    High 2
    Pause 100
    Low 2
  Case ...
    ... etc
End Select
What you are setting HIGH or LOW needs to be a pin number or port.pin identifier so what to use for those numbers would depend on which PICAXE you were using and how your hardware was wired-up.
Thank you sooooo much :D im kinda new to PICAXE. Im using it in my Year 11 (3rd year in High School) project and i only know the basic's like

Main:
High 1
Pause 100
Low 1
goto Main

so this is new to me and im slowly learning through PICAXE :p

Cheers Hippy :D
 
#12
Welcome to the PICAXE forum.

You can use the following code to get a number of value between 1 and 10 ...

Code:
Random w0
w1 = w0 // 10 + 1
And then you can use a SELECT-CASE command to handle what to do depending on the number ...

Code:
Select Case w1
  Case 1
    High 1
    Pause 100
    Low 1
  Case 2
    High 2
    Pause 100
    Low 2
  Case ...
    ... etc
End Select
What you are setting HIGH or LOW needs to be a pin number or port.pin identifier so what to use for those numbers would depend on which PICAXE you were using and how your hardware was wired-up.
okay so quick Question... is there a way to speed this up? i have 8 case's and it randomly selects fine but its too slow for the project i am making... not the LED on Pause LED off its the selection of the Case it takes (if i remember correctly) 3ish seconds where i need it to be 1 to 2 seconds long XD

Cheers,
Koopa
 

hippy

Technical Support
Staff member
#13
The RANDOM and SELECT-CASE should be executing with millisecond speed so there is perhaps something with your code slowing things down. Post your full code and members here can take a look at it.
 
#14
so here is my code (i hyper-linked it and its a GIF) so down the Left is the simulate and you can see it goes slow :/ i need that to be sped up


also does anyone know where (what pins) to put my AXE027 for my 18X chip?
 
Last edited:

hippy

Technical Support
Staff member
#15
Simulation runs slower than the code will on a real chip so you can see it as it simulates. You can speed things up by reducing the simulation delay slider at the bottom right when simulating.

Minimum operating circuits and where to connect the download cable to the PICAXE are shown in PICAXE Manual 1 - Getting Started.
 
Top