Bookmark and Share

Notice: On April 23, 2014, Statalist moved from an email list to a forum, based at

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: st: Random seeder

From (William Gould, StataCorp LP)
Subject   Re: st: Random seeder
Date   Wed, 29 Sep 2010 10:36:19 -0500

Antoine Terracol <> writes, 

> some time ago, there was a discussion on Statalist about 
> getting a random seed for Stata's PRNG. Bill Gould suggested
> that someone should write a little program to obtain (true)
> random numbers from 
> (see
> Based on R's random package, here's a first try, for anyone interrested

I like it.

In what follows, 

      1.  I make some minor but important fixes to Antoine's program, 
          and explain.

      2.  I improve and rename Antoine's program.  The improvement 
          deals with making sure the command fails if 
          someday changes their syntax or how they return results.

Everything is below.  I suspect from here on out, Antoine and I should 
work privately and just report the final result when we are done.

In my version of Antoine's program, I renamed the command -setrngseed-, and I
reversed Antoine's -setseed- option so that the option is now -nosetseed- 
and default is to reset the random-number seed.  The command has syntax

                setrngseed [, nosetseed min(#) max(#)]

The options are useful for debugging -setrngseed- and are probably not 
worth documenting.  I suggest that when Antoine writes the documentation, 
or he makes me write it, we document the syntax as simply being 


Here's what happens when you type it:

        . setrngseed
        (random-number seed set to 697429737)

Antoine's program, fixed

Here is Antoine's original program, updated, 

program define truernd, rclass
        syntax [, min(integer 1) max(integer 1000000000) setseed]
        tempfile rndseed
        tempname myseed

        quietly copy "`min'&max=`max'&col=1&base=10&format=plain&rnd=new" "`rndseed'", replace

        file open `myseed' using "`rndseed'", read text
        file read `myseed' value
        file close `myseed'
        return scalar rndvalue=`value'
        di "The value returned by is `value'"

        if "`setseed'"!="" {
                set seed `value'
                display "The seed was set to `value'"
                return scalar seed=`value'

Warning:  the line in the middle that begins -quietly copy- is a single,
long line and there are no blanks within the quioted string "http://...";.

I made trhee small changes, two important and the third more a  
matter of style. 

    1.  Antoine used the temporary filename `rndseed'.txt; I use `rndseed'.
        This is important.  Stata assumes you use temporary file 
        names in the form Stata supplied them.  When your program concludes, 
        Stata erases files with those names.  When Antoine 
        used `rndseed'.txt, Stata still attempted to erase `rndseed' 
        when the program concluded, and never even attempted to erase 

    2.  I enclose the temporary filename `rndseed' in double quotes everytime 
        I use it; I code "`rndseed'" rather than `rndseed'.
        This is important because, on some computers, the system 
        directory that contains the temporary files has blanks (spaces)
        in its name.  

    3.  Antoine used -`value'- and -``value''-; I used -value- and -`value'-.
        -value- in Antoine's code, and my update, is a macro.  Antoine put a
        temporary name in -value- and used macro `value' thereafter,
        meaning the contents of `value' were ``value''.  That was unnecessary;
        macros are private anyway.


Here is the -setrngseed- code.  

program define setrngseed, rclass
        version 11
        syntax [, MIN(integer 1) MAX(integer 1000000000) noSETseed]

        get_random_number `min' `max'
        local value "`r(result)'"

        if ("`setseed'"=="") {
                set seed `value'
                di as txt "(random-number seed set to `value')"
        else {
                di as txt " returns `value' (seed not set)"
        return scalar seed = `value'

program get_random_number, rclass
        args min max

        tempfile rndseed
        tempname myseed

        display as txt "(contacting"

        quietly copy "`min'&max=`max'&col=1&base=10&format=plain&rnd=new" "`rndseed'"

        file open `myseed' using "`rndseed'", read text
        file read `myseed' value1
        file read `myseed' value2
        file close `myseed'

        check_integer_result `value1'
        check_integer_result `value2'
        if (`value1' != `value2') {
                return local result `value1'

        di as err "{p 0 4 2}"
        di as err " behaved unexpectedly{break}"
        di as err " returned the same random"
        di as err "valiue twice, so the values are not"
        di as err "random or a very unlikely event occured."
        di as err "{p_end}"
        exit 674

program check_integer_result
        args value

        capture confirm integer number `value'
        if (_rc) {
                di as err "{p 0 4 2}"
                di as err " behaved unexpectedly{break}"
                di as err `"value returned was "`value'", which"'
                di as err "was not an integer."
                di as err "{p_end}"
                exit 674

The code looks different from Antoine's, but it's not much changed.
It looks different because I made my additions by adding subroutines, 
which I think makes the code more readable.

Here is what is substantively different:

    1.  I verify that the results returned by really are 

    2.  I ask for two random numbers rather than one.
        I verify that they are different.

I'm worried that might someday change their syntax or what 
they return.  If did that, Antoine's original program would 
probably break, but I wanted to make sure the program broke if results 
were not as expected.

By the way, I tried to make another change, but failed.

I tried changing 

        syntax [, MIN(integer 1) MAX(integer 1000000000) noSETseed]


        syntax [, MIN(integer 1) MAX(integer 2147483647) noSETseed]

but when I did that, reported an error.  I then tried 

        syntax [, MIN(integer 1) MAX(integer 2000000000) noSETseed]

and still reported an error.  So I changed back to how 
Antoine had it.  

Antoine, do you know how many bits bases their random number on?

-- Bill
*   For searches and help try:

© Copyright 1996–2018 StataCorp LLC   |   Terms of use   |   Privacy   |   Contact us   |   Site index