Qbasicnews.com

Full Version: Random Numbers
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3 4 5 6
you failed to specify the range. I've got an easy scheme to do what you ask...however, I need to know what range of numbers you are looking for!!! If you need a 10 bit number, there's no sense working with 8-bits, eh??!!!
Plasma357, your scheme does indeed produce a pattern. Plotting the output of your code indicates the problem:

SCREEN 11
DEFLNG A-Z
a = TIMER
DO
hold = g
'FOR j = 1 TO 10
M = 10000
M1 = 100
B = 7821
p1 = a \ M1
p0 = a MOD M1
q1 = B \ M1
q0 = B MOD M1
c = (((p0 * q1 + p1 * q0) MOD M1) * M1 + p0 * q0) MOD M
a = (c + 1) MOD M
g = a \ M1

'PRINT g;

'NEXT
PSET (hold, g)
LOOP
For speed purposes it precalculates 1024 'random' numbers and stores them into a array of singles.

--Code Begins--

FUNCTION Rand% (Max%)

STATIC Init%, RandomNums() AS SINGLE, Cnt%

IF Init% = 0 THEN

DIM RandomNums(1023) AS SINGLE

FOR I% = 0 TO 1023

NewSeed# = TIMER / 60
Temp# = (((NewSeed# * LastSeed#) - I%) MOD 100) / 100
LastSeed# = (NewSeed# + I% - Temp#)
RandomNums(I%) = Temp#

NEXT

Init% = -1

END IF

Rand% = RandomNums(Cnt%) * Max%
Cnt% = (Cnt% + 1) AND 1023

END FUNCTION
Quote:Plasma357, your scheme does indeed produce a pattern. Plotting the output of your code indicates the problem:

Heh, it's not exactly "mine", and you'll be hard-pressed to find a random number generator with no pattern.
[/quote]Heh, it's not exactly "mine", and you'll be hard-pressed to find a random number generator with no pattern.[/quote]

Plasma357, I respectfully disagree about the no pattern business;-) This one will repete...but not for a LONG time...like...if you are generating a billion numbers/second, it'd take something like 10^100 times longer than the age of the universe...it won't repete in your life time...also...if it does, just make it a bit wider, say 60,000 wide (eg DIM a(-32000 to 32000) AS INTEGER)

I don't show explicitly how to get a random number from this file, however it's straight forward. Just grab a bit sequence from the array (eg the first 32 bits of the array for a long integer) then convert it and stick it in a variable. When you need another one, either take the next block of 32 bits in the row, or step down a row.


Code:
'random number generator--Joe Campbell
'This pattern will repeat...it's 640-bit, so there are only
'4.6x10^192 possible states!!!  This pattern will only visit some
'fraction of the possible states...perhaps 25%  Still...you want a
'random sequence of 2-byte integers??? choose any screen position of the
'developed field and take 16-bits...move down a line then take another 16.
'the numbers represented will pass every test of randomness.  The center
'column of this unbounded automata is used by Mathmatica for generate random
'numbers.  See Stephen Wolfram's "A New Kind of Science".  I have implemented
'a strong secret key encryption using this so-called "rule 30" automata.

SCREEN 11
CLS

DIM a(1 TO 640) AS INTEGER
DIM b(1 TO 640) AS INTEGER

a(320) = 1       'starting condition...simplist case...a single bit in a field of zeros
                 'output is "just as random" as a for a more complex seed.
'RANDOMIZE TIMER: FOR t = 1 TO 640: a(t) = RND: NEXT t   'this is the "maximally random" starting condition


DO
FOR y = 1 TO 480

b(1) = (a(640) XOR (a(1) OR a(2)))           'special case wrapping
FOR x = 2 TO 639
  b(x) = (a(x - 1) XOR (a(x) OR a(x + 1)))    'normal case
NEXT x
b(640) = (a(639) XOR (a(640) OR a(1)))       'special case wrapping

FOR x = 1 TO 640
  PSET (x, y), b(x)
  SWAP a(x), b(x)
NEXT x

NEXT y

LOOP
Nope, nope.

Your random number generator has a pattern that is created from the code.

The code *is* the pattern.
Quote:Nope, nope.

Your random number generator has a pattern that is created from the code.

The code *is* the pattern.

Agamemnus,

I guess pattern is the wrong word...every sequence of numbers has a pattern...it's own. What I meant was that a pattern would be seen if the "random" numbers were plotted. That is, the output of the random number generator can be somehow represented with less data than the output itself. It's really a philosophical question. If every detail of a system is known...can one predict the outcome of that system? I suspect the answer is yes, even for radioactive decay...however, the amount of computation required should be equivalent to letting the system develop on it's own. As such...it is basically unanswerable without taking a wait and see approach. The same is true for the "rule 30" automata.

I adjusted the code to make it a random number generator with output in the 0 to 1 range, double precision. Of course if you seed it with the same value you will get the same sequence of numbers. However, that doesn't change the fact that the number sequence will stand up to any test for randomness that you can throw at it!!

Change the seed, and the sequence will be just as "random"...but a different sequence. Evaluate the numbers...you will find no local or long-distance coorelation between the numbers.

the other submissions do not pass the test:

SCREEN 11
DO
PSET(RND*640, RND*480)
LOOP

Furthermore, some of them rely on TIMER as input...which is essentially a random input to the system. My method is different. the only input is a single bit, and the output appears to follow no pattern...although it is not "random" in that it is reproducable. I should have used function, but wrote it with calls instead...sorry for the awkwardness...Here's the code...It doesn't need to be this long, but it helps make it easier to understand.


Code:
DECLARE SUB seed (a%(), randomnum#, b%(), maxwidth%)
DECLARE SUB stepautomata (a%(), randomnum#, b%(), maxwidth%)
DECLARE SUB rando (a%(), randomnum#, b%(), maxwidth%)
DEFINT A-Z
SCREEN 0

maxwidth% = 1000    'Set maxwidth% as big as you want, but at least as big
'as the bit-depth of the random number...in this case 32 is absolute minimum.
'if you make it small, the automata will repete and non-random output will
'be observed.  
                                                                  
DIM a(0 TO maxwidth%) AS INTEGER       'arrays that hold automata
DIM b(0 TO maxwidth%) AS INTEGER       'a() is last complete line, b() is next line

CALL seed(a%(), randomnum#, b%(), maxwidth%)

'after this line, random numbers are available with CALL rando
'for example, the following loop fills screen with random dots.

SCREEN 11
DO

CALL rando(a%(), randomnum#, b%(), maxwidth%)  'get a random number...
  x = 640 * randomnum#                           'and scale it for your purposes
CALL rando(a%(), randomnum#, b%(), maxwidth%)  'get another...
  y = 480 * randomnum#

PSET (x, y)

LOOP UNTIL INKEY$ <> ""
END


SUB rando (a%(), randomnum#, b%(), maxwidth%) STATIC

IF position + 32 > maxwidth% THEN         'checks to see if a new line is needed
  CALL stepautomata(a%(), randomnum#, b%(), maxwidth%)  'update the array a%()
  position = 0
END IF

grabaword# = 0                      'reset value between calls

FOR x = 0 TO 31                     'bit-depth of random number
grabaword# = grabaword# + (a%(position) * (2 ^ x))    'grab a 32 bit chunk of a%() and convert to a double precision number
position = position + 1            'keep track of where you are on in array
NEXT x
                                               'note...x=32 here
randomnum# = grabaword# / ((2 ^ x) - 1)        'normalize so that randomnum#
                                               'will be in the range 0 to 1
END SUB                                        'just like the basic function RND

SUB seed (a%(), randomnum#, b%(), maxwidth%) STATIC
PRINT "seeding"
'this is needed to get array filled with indeterminate data.



a%(0) = 1        'starting condition...simplest case...a single "1" in a
                 'field of zeros.  The output is "just as random" as with
                 'a more complex seed. Try the next line to see this.
                 'this is the "maximally random" starting condition:
                 'RANDOMIZE TIMER: FOR t = 0 TO maxsize%: a(t) = RND: NEXT t
                
FOR t = 0 TO maxwidth% \ 2       '2 is used b/c automata expands in both directions
CALL stepautomata(a%(), randomnum#, b%(), maxwidth%)
NEXT t

CLS
END SUB

SUB stepautomata (a%(), randomnum#, b%(), maxwidth%) STATIC

'this steps the automata forward...and is the source of the randomness
   b%(0) = (a%(maxwidth%) XOR (a%(0) OR a%(1)))    'special case wrapping left
FOR x = 1 TO maxwidth% - 1
   b%(x) = (a%(x - 1) XOR (a%(x) OR a%(x + 1)))    'normal case
NEXT x
   b%(maxwidth%) = (a%(maxwidth% - 1) XOR (a%(maxwidth%) OR a%(0)))   'special case wrapping right

FOR x = 0 TO maxwidth%  'puts new values in a%()
  SWAP a%(x), b%(x)
NEXT x
END SUB
Oh.....hm... ok.

I might find a correlation..............................................
Quote:Oh.....hm... ok.

I might find a correlation..............................................

I seriously doubt it ;-)

I may not be able to spell correlation, but I sure can tell you that numbers that my program spits out don't have one;-)

Cheers. Do I win the challenge, or not? The other entries don'pass the:

PSET (random(x), random(y))

test...or they use timer to seed...mine passes. Any entries that use another scheme and pass??
I didn't have time to see how long it takes for a 'pattern' to form... but it seems pretty 'random' and on speed test's it was as fast as qb's RND when compiled and sometimes slightly faster.

both averaging around 88000 numbers a second
highest my routine got so far was 92534.

keep in minf these numbers are based on the program being compiled, my routine averaged around 64000 uncompiled.

DEFINT A-Z
FUNCTION Rand (Min, Max)

STATIC Cnt AS LONG, Cnt2 AS LONG, LastMin, LastMax
STATIC LastValue

Ran = Max - Min

Cnt = (Cnt + (LastMin + LastMax)) AND 32767
Cnt2 = (Cnt2 + ((Cnt + (Max + Min)))) AND 32767
D& = ((Cnt + Cnt2) + (Ran + Min))
D2 = (D& + LastValue) MOD (Ran + 1) + Min
Rand = D2

LastValue = D2
LastMin = Min
LastMax = Max

END FUNCTION
Pages: 1 2 3 4 5 6