QBasic / QB64 Discussion Forum      Other Subforums, Links and Downloads
 Return to Index  

More discussion on RND

March 9 2004 at 1:37 PM
  (Login Mac36)


Response to Use of RANDOMIZE TIMER

Why does RND always give the same numbers?

Short answer: You need to put RANDOMIZE TIMER at the beginning of your program.

Long answer:

If you keep doing PRINT RND, you will get a sequence of numbers that appear to be random. In fact, they are a fixed sequence of numbers and when you get to the end, it repeats. This is not a big problem, because the sequence is 16,777,216 numbers long!

Although you see numbers returned in the range 0-0.9999999..., in reality the sequence is a list of unique numbers in the range 0-16777216. The current number retained by QBasic is called the SEED. When you do Y=RND, the SEED is used to compute the next SEED which is retained. Then Y is set to that new SEED/16777216.

When you first start QBasic, the SEED is arbitrarily set to 327,680. Therefore, you always start at the same point and get the same numbers.

If you do RANDOMIZE TIMER, the SEED is set to some other value.

So a good practice is to debug your program without RANDOMIZE TIMER, so you always get the same results and can repeat test cases. Then when your program is debugged, put RANDOMIZER TIMER as the first instruction. Voila!

Mac

REALLY, REALLY LONG ANSWER:


QBasic and VBasic result of RND
===============================

If you start a QBasic or VB program and print RND before any other randomize statement such as RANDOMIZE TIMER, you will get 0.7055475115776062 (rounded). That is 11837123/16777216. You will get this every time you run the program. In more detail, you get these results for RND*16777216:
      ...
  12135126
   7796289
    327680 <Last number before sequence repeats  
  11837123 <First number at start of program
   8949370 <Next number returned by RND
   9722709 <etc.
   4858052
   5065847
      ...

The initial seed was 327680 = RND(0) * 16777216

RND(0) * 16777216 always is the current seed value.

If you insert RANDOMIZE TIMER at the beginning of your program, another number is selected as the initial seed as a function of the timer. This gives different start place (seed) in the sequence every time you run the program.

Each time you do RND, the following occurs (or something like it)
    Temp# = (16598013# * Seed#) + 12820163
    Seed# = (Temp# - INT(Temp# / 16777216)) * 16777216
    Value-to-be-returned = Seed# / 16777216

What happens in the case of, for example "RANDOMIZE 3"?
      ...
   7376207
    914134
  10001985
   4196352 <Last number before sequence repeats
   2328259 <First number after RANDOMIZE 3
  14407290 <Next number returned by RND
  12223317 <etc.
   7841988
  14988407
      ...

The initial seed was 4196352 = RND(0) * 16777216

But what happens if we first do Y=RND (which puts us at a different place in the sequence) and then do RANDOMIZE 3?
      ...
   2378966
   4034625
  10039808
   4196547 <Last number before sequence repeats
    938106 <First number after Y = RND: RANDOMIZE 3
   9114965 <Next number returned by RND
  13497028 <etc.
   9033335
  12105566
      ...

The initial seed was 4196547 = RND(0) * 16777216

4196352 is not 4196547 (But close, differs by 65*3)

I did various experiments and could not determine the exact algorithm, but basically, RANDOMIZE N produces a seed that is a function of N and the current seed. Thus it is a poor way to seed for cryptography or game recovery or any application where you want to get the same results again.

RANDOMIZE 3 will always give the same result if issued as the first instruction, but whenever issued after other RND usage, it will give other results.

This is as opposed to Y = RND(-N)
      ...
  15922689
   4194496
  16161923 <Last number before sequence repeats
  15308090 <First number after Y = RND(-3)
  16533269 <Next number returned by RND
   7429508 <etc.
  12228151
  13989918
      ...

The initial seed was 16161923 = RND(0) * 16777216

But even after other RND operations, Y = RND(-3) always sets the seed to 16161923 (by whatever function of -3 is used)

Y = RND(-N) will always reset the sequence to the same place.

That is about all there is to RND, but some may insist "These are therefore not random numbers, they are pseudo-random numbers."

This is generally unimportant intellectualism run amok. Who cares? The numbers are random enough for games we write in QBasic, for screen savers, etc., etc.

Even for cryptography, the only problem is that the sequence is not long enough.

Note that if I use INT(RND*10), I will get a digit. If I use it again, I will get another digit.

There are 16777216/10 cases of the first digit.
There are 16777216/100 cases of the pair
So if I gave you a three-digit sequence, there would be 16,777 cases of what the next digit would be. In other words, it is random!

True, if I gave 8 digits, you might be able to find the place in the RND series that gives those digits, and you might find there is no other such place. In that case, the next digit is no longer random. You know what it will be.

So RND would be bad to use in a casino. If you knew how it was being used, you could theoretically compute the next number to come up on the roulette table.

But even that is not true if you use RANDOMIZE TIMER. Assume after bets are placed and the SPIN key is pressed, you issue that command. Then nobody will be able to predict what number will come up. RND will return a true and perfect random number.

More Details
============

http://www.network54.com/Hide/Forum/message?forumid=178387&messageid=1051100317

http://www.network54.com/Hide/Forum/message?forumid=178387&messageid=1012085898


    
This message has been edited by iorr5t on Mar 30, 2004 9:08 AM


 
 Respond to this message   
Responses