Construct your own random number generator

vegaseat 1 Tallied Votes 6K Views Share

In Las Vegas random numbers move billions of Dollars in and out of gamblers' pockets. For the mildly inquisitive here is a test of three simple generators.

// evaluation of three simple random number generators
// Written in Turbo C, modified for Pelles C
// get Pelles C for free: http://smorgasbordet.com/pellesc/index.htm
// this C package comes with a great IDE


#include <stdio.h>   // printf(), getchar(), puts()

// three different custom random number generators
int rand1(int lim);
int rand2(int lim);
int rand3(int lim);

int main(void)
{
        int  k, rnd1, rnd2, rnd3, sum1, sum2, sum3;

        sum1 = sum2 = sum3 = 0;
        puts("Random numbers between 1 and 44:\n");
        printf("%15s%10s %10s %10s","Custom functions","rnd1()","rnd2()","rnd3()");
        for (k = 0; k < 40; k++) {
                rnd1 = rand1(44);   // method one
                rnd2 = rand2(44);   // method two
                rnd3 = rand3(44);   // method three
                printf("\n%25d %10d %10d",rnd1,rnd2,rnd3);
                sum1 += rnd1;  
                sum2 += rnd2;
                sum3 += rnd3;
        }
        printf("\n\n%15s%10d %10d %10d   (ideal 22)\n",
        "   Average:",sum1/k,sum2/k,sum3/k);
        getchar();  // wait
        return 0;
}

//
// returns random integer from 1 to lim
//
int rand1(int lim)
{
        static long a = 100001;

        a = (a * 125) % 2796203;
        return ((a % lim) + 1);
}

//
// returns random integer from 1 to lim (Gerhard's generator)
//
int rand2(int lim)
{
        static long a = 1;  // could be made the seed value

        a = (a * 32719 + 3) % 32749;
        return ((a % lim) + 1);
}

//
// returns random integer from 1 to lim (Bill's generator)
//
int rand3(int lim)
{
        static long a = 3;

        a = (((a * 214013L + 2531011L) >> 16) & 32767);
        
        return ((a % lim) + 1);
}

Dani AI

Generated

If you roll your own generator, two pitfalls to avoid are weak parameters and weak seeding. Many simple generators here are variants of the linear congruential generator (LCG): x = (a*x + c) mod m. The quality depends critically on the choice of a, c, and m; poor choices produce visible patterns and short periods (see the LCG discussion and good parameter sets in Wikipedia’s LCG article). Also note that seeding with whole seconds (e.g., time(NULL)) gives only 1 Hz granularity; combine multiple sources and seed once, not per sample. Finally, avoid % n for bounding, which introduces modulo bias; use rejection sampling as explained in PCG’s bounded-rands post.

Here is a compact, fast PRNG that is much better than a naive LCG while still easy to implement:

#include <stdint.h>
#include <time.h>
#ifdef _WIN32
#include <windows.h>
#define GETPID() GetCurrentProcessId()
#else
#include <unistd.h>
#define GETPID() getpid()
#endif

static uint32_t s;  // state

static inline uint32_t xs32(void) {
    uint32_t x = s;
    x ^= x << 13;
    x ^= x >> 17;
    x ^= x << 5;
    return s = x;
}

static inline uint32_t rand_bounded(uint32_t n) { // uniform in [0, n)
    uint32_t t = UINT32_MAX - (UINT32_MAX % n), r;
    do { r = xs32(); } while (r >= t);
    return r % n;
}

void rng_init(void) {
    uint32_t seed = (uint32_t)time(NULL) ^ (uint32_t)GETPID() ^ 0x9E3779B9u;
    s = seed ? seed : 1u;
}

For security-sensitive uses (gambling, crypto), do not use custom PRNGs; use your OS CSPRNG (for example, getrandom() on Linux as documented in getrandom(2)) or a NIST-approved DRBG (NIST SP 800-90A). Testing with suites like PractRand or Dieharder can help validate statistical properties.

bumsfeld 413 Nearly a Posting Virtuoso

I like simpel stuff!

ultirian 0 Newbie Poster

How would you implement this using the time as the seed?

nanodano 0 Junior Poster in Training

To use the time as the seed is very simple.

Make sure you include the <ctime> header.

#include <ctime>

Then, inside ctime there is a function you can call like this:

time(0);

When you pass this method zero, it returns the time elapsed since January 1, 1970. This way you are guaranteed a differerent number each run time(if you run it less than 1 time per second).

Ok, so back to "how to make the time the seed" question. In these code examples replace the arbitrary number assigned to a with:

static long a = long(time(0));

Next, perform your random number generation using whichever method.

kirti4 0 Newbie Poster

why in 1st method u have used value 100001 to intialize the varible a.is it a range of something.

irum.nageen.3 -6 Newbie Poster

It is one of the simplest logics, got it from a blog. in this logic you can limit the random numbers with that given modulus(%) operator inside the for loop,its just a copoy and paste from that blog, but any way check it out:

[

// random numbers generation in C++ using builtin functions
#include <iostream>

using namespace std;

#include <iomanip>

using std::setw;

#include <cstdlib>   // contains function prototype for rand

int main()
{
    // loop 20 times
    for ( int counter = 1; counter <= 20; counter++ ) {

        // pick random number from 1 to 6 and output it
        cout << setw( 10 ) << ( 1 + rand() % 6 );

        // if counter divisible by 5, begin new line of output
        if ( counter % 5 == 0 )
            cout << endl;

    }

    return 0;  // indicates successful termination

} // end main
- See more at: 
rubberman 1,355 Nearly a Posting Virtuoso Featured Poster

Two problems. One is that this thread is 8 years old! Two is that writing good random number generators is not a trivial undertaking, and thinking it is just shows your ignorance of the subject. Read this: http://www.phy.ornl.gov/csep/CSEP/RN/RN.html

From the document, 2 relevant quotes:

Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin. -- John von Neumann (1951)

Anyone who has not seen the above quotation in at least 100 places is probably not very old. -- D. V. Pryor (1993)

nitin1 commented: those quotes are simple awesome!! :D +3
deceptikon commented: Yes. +12
JorgeM commented: very true.. nice.. +12
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.