Home
CBM
  ASCII-X
  BASIC
    Disk Commands
    Enter RUN mode
    Program Format
    Secret Variables
    Variable Format
    Expressions
    Keywords
      (divide)
      (equal)
      (less)
      (minus)
      (more)
      (multiply)
      (plus)
      (power)
      Abs
      And
      Append
      Asc
      Atn
      Auto
      Backup
      Bank
      Begin
      Bend
      Bload
      Boot
      Box
      Bsave
      Bump
      Catalog
      Char
      Chr
      Circle
      Close
      Clr
      Cmd
      Collect
      Collision
      Color
      Concat
      Cont
      Copy
      Cos
      Data
      Dclear
      Dclose
      Dec
      Def
      Delete
      Dim
      Directory
      Dispose
      Dload
      Do
      Dopen
      Draw
      Ds
      Ds string
      Dsave
      Dverify
      El
      Else
      End
      Envelope
      Er
      Err
      Exit
      Exp
      Fast
      Fetch
      Filter
      Fn
      For
      Fre
      Get
      Get num
      Getkey
      Go
      Gosub
      Goto
      Graphic
      Gshape
      Header
      Help
      Hex
      If
      Input
      Input num
      Instr
      Int
      Joy
      Key
      Left
      Len
      Let
      List
      Load
      Locate
      Log
      Loop
      Mid
      Monitor
      Movspr
      New
      Next
      Not
      Off
      On
      Open
      Or
      Paint
      Peek
      Pen
      Pi
      Play
      Pointer
      Poke
      Pos
      Pot
      Print
      Print num
      Pudef
      Quit
      Rclr
      Rdot
      Read
      Record
      Rem
      Rename
      Renumber
      Restore
      Resume
      Return
      Rgr
      Right
      Rlum
      Rnd
      Rreg
      Rspcolor
      Rsppos
      Rsprite
      Run
      Rwindow
      Save
      Scale
      Scnclr
      Scratch
      Sgn
      Sin
      Sleep
      Slow
      Sound
      Spc
      Sprcolor
      Sprdef
      Sprite
      Sprsav
      Sqr
      Sshape
      St
      Stash
      Step
      Stop
      Str
      Swap
      Sys
      Tab
      Tan
      Tempo
      Then
      Ti
      Ti string
      To
      Trap
      Troff
      Tron
      Until
      Using
      Usr
      Val
      Verify
      Vol
      Wait
      While
      Width
      Window
      Xor
    Syntax
    Tokens
  C128
  D64plus
  Disk
  Escape Codes
  Hardware
  PCxface
  PETSCII
  Pet2asc
Futurama
IBM PC-AT
Contact
Games
Glossary
Hall of fame
Hall of shame
Miscellaneous
Privacy policy
Programming
Twisty puzzles
KeywordAbbreviationToken (hex)Version(s)Classification
RNDR{Shift+N}BB1.0+Function

 Syntax 
RND value )
 
ParametersTypeLegal Value(s)Note(s)
valueNumeric
any
 
ReturnsTypeValue(s)Note(s)
resultFloating-point
0 to 1
up to, but not including, 1
 
 Purpose 
Calculate a psudo-random number.
 
 Remarks 
The RND function is primarily used to generate a psudo-random number.  Psudo-random means the value is difficult predict, but not truly random.  CBM BASIC provides two ways to get a "random" number.  One way is to supply a value of zero to RND; in this case RND will generate a "random" number based on hardware timers and also update a Secret Variable called the seed.  The second way is to supply any positive value to RND; in this case it will generate a "random" number based on the current seed (and update the seed in the process).  I prefer to combine the methods: use a zero value at the start of the program to set a "random" seed based on the hardware timers and then use a positive value in the main loop of the program to generate a "random sequence".  I do this to avoid potential skewing of the results based on the periodic nature of the hardware timers.
 
Another, rarely used option, is to pass a negative value to RND which will set a specific seed.  This may be useful for testing as it will result in the same sequence of "random" numbers if you only use RND(1) in the future (i.e., in any positive value).
 
The result will be a floating-point number from zero up to, but not including, one.  To get an an integer number between min and max (inclusive), use the forumla:
 R = min + INT( (max - min +1) * RND(1) )
 
For example, to get a random number from 1 to 6 to simulate the roll of a die, the forumula would work out as R = 1 + INT(6*RND(1)).
 
There has been some controversy around the RND function.  Mainly this involves the "quality" (or lack thereof) of the random values generated.  From my research, the poor quality seems to be a more serious issue in other (non-CBM) versions of BASIC.  This is probably due to a combination of poor algorithm along with limited precision (CBM features 32-bit floats, while most other 8-bits use only 24-bit floats).  In CBM BASIC, it seems many programs are using a 0 value which may reduce quality based on the peiodic nature of the hardware timers (as explained above).  There are several statical measures that can be applied to a sequence of numbers, and which ones are important tends to vary upon the intended use of the random numbers; hence another reason for debate.  My limited experiments (using my preferred/combined method) show that usually all values in 1-d or 2-d sense will eventually occur, and most of them with roughly the same frequency.  In a 3-d and 4-d sense the "random" numbers often will hit all possible combinations, but in a few cases (an "unlucky seed") some combinations never occur.  I think this could be avoided (but haven't verified) if you call RND(0) to re-seed the sequence on rare occassions (like maybe 1 in 5000, or even less often).
 
Another thing to consider is that the quality of the results may depend on how often / when you call RND.  If you call it routinely in a programmed loop (for example to draw a field of "stars" on a bitmap) the RND function will get called at a fairly predictible rate so that RND(0), which bases its results on the hardware timers, may be heavily skewed.  On the other hand, if you only occassionaly or "randomly" call RND(0) (for example, when the user performs a certain task) it may give "better" results than RND(1); the reason being that the user (if human) will generally not do things on a very precise time schedule (thus the hardware timers will tend to be "randomly out of sync" relative to the last time they were checked).  Anyway, I think using RND(0) to initialize the seed and RND(1) in loops is a good strategy.
 
If you don't trust BASIC (or my experimental results), some CBM machines have a SID chip which can be programmed to generate "random" numbers too; I haven't compared the quality of the two methods, but POKEing and PEEKing seems like it would be slower than using RND.
 
BASIC sets the seed to a constant value stored in ROM on power-up.  Thus, if you use RND(1) without initializing the seed your program will generate the same set of "random" numbers if you run it after power-up.  The BASIC versions are not consistant about the initial value returned by RND(1) or how they update the seed when given a negative value.  Thus on a single machine, you can set a specific seed (with either a negative value or the power-up method) and get a reliable sequence of numbers; but running the same program on a different machine may give different results... compare and contrast the examples.
 
If the value is omitted or not a valid expression, SYNTAX ERROR is generated.  If the value is not numeric, a TYPE MISMATCH ERROR occurs.
 
I almost forgot!  Some other BASICs use the value supplied to RND to determine the range of the result.  As explained above, CBM BASIC always returns a result in the range of 0 to 1 (the value is only used to specify a method used to generate the result or possibly set an initial seed).
  
Examples (Plus/4 or C128):
PRINT RND(1)   : REM result after power-up
 1.07870447E-03 
 
READY.
PRINT RND(1)   : REM the next number in the "random" sequence
 .793262171

READY.
PRINT RND(-1)  : REM set a specific seed
 2.99196472E-08

READY.
PRINT RND(1)   : REM the next number in the "random" sequence
 .328780872

READY.
PRINT RND(0)   : REM this will be "random" unless you have very precise timing...
 .252642419

READY.
  
Examples (C64):
PRINT RND(1)   : REM result after power-up
 .185564016 
 
READY.
PRINT RND(1)   : REM the next number in the "random" sequence
 .0468986348

READY.
PRINT RND(-1)  : REM set a specific seed
 2.99196472E-08

READY.
PRINT RND(1)   : REM the next number in the "random" sequence
 .328780872

READY.
PRINT RND(0)   : REM this will be "random" unless you have very precise timing...
 .601563811

READY.
  
 Compare With 
 
 Contrast With 

© H2Obsession, 2014