LB's Pseudo-Random Number Generator.

For most purposes the LB generator works fine.

However for a few specialist users it is worth being aware that it is not perfect, quite apart from the mathematical and philosophical impossibility of having an algorithmic generator of randoms! These are dealt with well in Wikipedia.


Most languages implement a linear-congruent generator. If the constants for this are correctly chosen for maximal length, it will repeat after visiting all numbers below the modulus limit one time. LB's PRNG is of unknown type.

In LB, the 'randomize()' command is used to re-seed the generator. LB itself seeds it at start-up. 'Randomize' is intended to allow repeated production of the same sequence- useful for de-bugging, and in xor-encrypting/ decrypting.


  • 1 Distribution is not uniform.

    Bias is unusual in other languages. Cycle-length in these is sometimes short, or distribution sparse, but generally uniform. However historically there have been some very poor implementations, not detected for some time!
    However LB's PRNG shows consistent small bias. As an example, if in LB we count RND( 1) >0.5, bias will be around 0.5%.

    The diagram shows over 15 million throws of random numbers, saved and displayed in 1000 bins. Low numbers are over-represented, and high ones under represented. Note however the suppressed origin- the frequency with which particular randoms occurred vary by +/- 3%, and the bias is well under 1%.

  • 2 In LB spec'n it states that without explicitly calling RANDOMIZE, sequence will be different each time program is run.
    However there are cases that starts RND somewhere near in the sequence. If you look further on in the new sequence you may find the earlier one.

  • 3 Small changes in seed used with RANDOMIZE seem to lead to small changes in next RND value. Specified seed range (0 .. 0.9999) is not convenient for using with RANDOMIZE, but closely similar seeds should give very different random sequence starts.

  • 4 If RANDOMIZE is called with wrong seed (like -1), it will "break" subsequent calls for RND.

    The error will stop LB on the next to RND(), and will now appear even if the LB program is restarted with RANDOMIZE is now edited and called with a valid argument. The only other way to clear the error situation is to restart the LB IDE.


  • Copy each of the example demonstrations and run separately......
    
    '1  _________________________________________________________________________________________________________________
    '   Leave this program running for several tens of minutes...
    
        WindowWidth  =1000
        WindowHeight = 600
    
        open "Histogram for LBB's version of 'rnd( 1)'." for graphics_nsb_nf as #w
    
        #w "trapclose [quit]"
    
        #w "down"
        for i =1 to 255
            #w "color "; 255 -( i mod 256); " 0 "; i mod 256
            #w "backcolor "; 255 -( i mod 256); " 0 "; i mod 256
            #w "goto 0 "; i /255 *600 -3
            #w "boxfilled 1030 "; i /255 *600 +3
        next i
    
        #w "getbmp scr 0 0 1050 610"
    
        dim new( 1000)
    
        timer 1000, [display]
    
    [over]
        c =c +1
        r =int( 1000 *rnd( 1))
        new( r) =new( r) +1
        scan
        goto [over]
    
    [display]
        timer 0
        #w "cls"
        #w "drawbmp scr 0 0"
    
        mx =0
        mn =10^10
        for i =0 to 999
            mx =max( new( i), mx)
            mn =min( new( i), mn)
        next i
        range =mx -mn
        #w "color black; backcolor black"
        for i =0 to 999
            '#w "color "; i mod 256; " 0 "; 255 -( i mod 256)
            #w "up ;   goto "; i; " 0"
            #w "down ; goto "; i; " "; int( 589 -( new( i) -mn) /range *600)
        next i
        #w "color yellow ; backcolor darkblue"
        #w "up; goto 400, 50"
        mean =c /1000
        #w "\ Throws ="; c; "   Mean ="; mean; "    +/- "; using( "###.#", 100 *( mx -mn) /2 / mean ); "%. Range "; mn; " to "; mx; "."
        #w "flush"
        timer 60000, [display]
        goto [over]
    
    [quit]
        close #w
        timer 0
        end
    
    
    '2  _________________________________________________________________________________________________________________
    '   Run this program repeatedly, several times in succession. Compare outputs.
        for i =1 to 10
            print using( "#.######", rnd( 1)); "  ";
        next i
        print
    
        end
    
    
    '3  ________________________________________________________________________________________________________________
    
        randomize( 0.123456)
        for i =1 to 10
            print using( "#.######", rnd( 1)); "  ";
        next i
        print
    
        randomize( 0.123457)
        for i =1 to 10
            print using( "#.######", rnd( 1)); "  ";
        next i
        print
    
        end
    
    '4  _________________________________________________________________________________________________________________
    
    '   Runs as-is. REM out the first randomize and try one of the other two.
    '   Program now fails.
    '   Re-REM  to how it is now. Run will still fail. Save in this form.
    '   Restart IDE & program runs without erroring.
    
        print rnd( 1)
    
        'randomize( 0.123456)
        'randomize( -1)
        'randomize( 123)
    
        print rnd( 1)
    
        end
    
    '   _________________________________________________________________________________________________________________
    
    
    

    I again emphasize that the errors discussed here are of little importance for gaming programs or even physics simulations. However sophidssticated users should be aware of the situation. It is hoped LB5 will have a better PRNG. Meanwhile, the Mersenne Twister is available as an eaily-called dll to use instead, with only a small speed penalty.