Random Numbers

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
vicist
Vic 20 Afficionado
Posts: 352
Joined: Tue Oct 09, 2012 5:26 am
Location: Sheffield, UK

Random Numbers

Post by vicist »

I recently reported that the rnd(0) function was not working in vice (now fixed).

But, inspired by Mike's post
http://sleepingelephant.com/ipw-web/bul ... ber#p85580

I tried this out in vice

Code: Select all

10 print chr$(147):c=38399:s=7679
20 for x=1 to 506:poke c+x,6:next
30 x=int(rnd(0)*506)+1
40 poke s+x,160:goto 30
and got a disappointing result.

So I changed rnd(0) to rnd(1) in line 30 and got a much more satisfying result.

Thinking that it was still a problem in vice, I typed the prog into a real vic.
OUCH!!! - similar results :cry:

Mike wrote
one needs to wonder if it actually even ever worked on real hardware
All this time I assumed that this was how to generate random numbers, after all, most example programs and type-ins that need random numbers use rnd(0).
It's not too bad with small numbers like simulating dice throws (1-6 or 1-12) but the larger the range the worse it gets.
After reading the programmers guide, I think that rnd(0.5) might be the better choice.

Any thoughts?
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Random Numbers

Post by Mike »

The Programmer's Reference Guide gives three different argument ranges for RND(X):

- X>0 takes the internal seed and generates a new random number from it (the exact value of X doesn't matter at all),

- X=0 generates a random number from internal timers (bad!), and reinitialises the seed also from those timers,

- X<0 just re-initialises the seed from X, the result is unusable as random number.

Especially the commonly observed usage of RND(TI) just works the same as RND(1), it doesn't generate "more random" numbers!
Mike wrote:one needs to wonder if it actually even ever worked on real hardware
At the time I wrote this I (errorneously) thought RND(0) would take its result from the Jiffy IRQ timers. That would have implied a strong correlation time-wise between press of RETURN (due to the keyscan) and the calculation of RND(). However, that's not the case. As you've seen, your observation uncovered a true bug in the VIA emulation of VICE.

Coming back to the mainly intended handling of RND():

- You'd normally initialise the seed of RND() in the first line of the program with something like "X=RND(-TI):CLR", which uses the negative value of the jiffy clock since start-up to seed the random generator. The CLR command then clears the variables, so the program can build up the variable list once again in the order of most used variables first, if so desired. For this check the various threads discussing this.

- You'd then only ever use RND(1) generate a random number between 0 (inclusive) and 1 (exclusive), and use the standard construction of INT(RND(1)*(B-A+1))+A to get integer random numbers between A and B (both inclusive). The expression "(B-A+1)" would normally be written as constant number, as, for example, in INT(RND(1)*6)+1 to get random numbers in the range 1..6.

...

That being said, the RND() function uses a *broken* variant of the linear-congruential generator. It exchanges bytes of the generated result, and thus brings parts of the random number into front that aren't nearly as random! Instead of a period of 2^32, RND() only produces tenthousands of small cycles, most of them in the order of ~58000 numbers, but there are also small cycles where RND() already repeats after ~750 numbers! Other numbers are only ever produced once, and then never again.

This is however an issue unrelated to VICE, and will also occur on real hardware. Only remedy is to use an own, better, generator.
Post Reply