views:

440

answers:

12

This may sound like an odd question, but where can I find a random number generator that works in C or C++ that is not very good?

Context: I'm creating some tree graph plotting software and testing it by using multi-digit random numbers (so each digit becomes a node in the tree). The random number generator I've been using - which is the one that comes with the GNU C++ compiler - gives me a nice spread of values. That's good, but I want to see how the table looks when the numbers clump together and are less homogenous.

Can anyone suggest a random number generator that has been proven to be not-so-random?

(Oh, any anyone who links to xkcd and/or suggests I just return 4 will get sarcasm in response).

A: 

use srand, but add a seed to it which doesnt change much. in fact, all pseudo-random-number-generator behave this way.

basically, just seed it with 1, then 2 then 3 .. pretty soon you will see that the "random" numbers are not so random.

Andrew Keith
Are you suggesting reseeding every time before getting a new number?
thornate
yeah .. if you re-seed every time, you essentially break the PRNG since its only generating the next number. If you repeat the seed, then it gets worst, generating the same number over and over.
Andrew Keith
A: 

Actually, the rand() function is really quite bad. I use GameRand which is REALLY simple, and produces decent results, but it may still not be crappy enough for you.

Victor Liu
It depends. I believe GCC/GLibc implements `rand()` with `random()` and that their PRNG is actually pretty good.
Chris Lutz
Citation: http://www.gnu.org/s/libc/manual/html_node/BSD-Random.html#BSD-Random Quote: "There is no advantage to using these functions with the GNU C library; we support them for BSD compatibility only." So any data that compares `rand()` to BSD's `random()` doesn't apply to GLibc.
Chris Lutz
+1  A: 

A C++ solution:

class ClumpedRandom
{
  public:
    ClumpedRandom(int maxClumpSize) 
     : mMaxClump(maxClumpSize)
     , mCurrentClumpSize(0)
     , mCurrentCount(0)
    {
       if (!sInitialized) {
         sInitialized = true;
         srand(time(NULL));
       } 
    }

    int operator()()
    {
      if (++mCurrentCount >= mCurrentClumpSize) {
        // Need a new clump:
        mCurrentClumpSize = rand() % mMaxClump;
        mCurrentCount = 0;
        mCurrentValue = rand();
      }

      return mCurrentValue;   
    }


  private:
    static bool sInitialized;
    int mMaxClump;
    int mCurrentClumpSize;
    int mCurrentCount;
    int mCurrentValue;
};

It produces random length runs of at most maxClumpSize instances of the same random number value. (I didn't say that very clearly...hopefully you get the idea).

Drew Hall
Why don't you `srand()` in your ctor? You could have a private static variable that tells you if you've called `srand()` or not, and if you haven't you can call it. It's fairly simple (though if your user calls `srand()` on his own it may fail).
Chris Lutz
@Chris: I thought about it but there is no benefit to srand()'ing more than once if he made multiple ClumpedRandom objects. In my own code I'd use a stateful PRNG object rather than srand()/rand() to assure truely independent streams. Sounds like his application doesn't really need to worry about quality all that much anyways though...
Drew Hall
@Chris: Oh, I misread you at first. Sure, we could do that...edit forthcoming...
Drew Hall
I'm not a true guru, so I have to ask: Does `static bool sInitialized;` default to 0, or is it uninitialized like a regular variable and contain garbage?
Chris Lutz
It will default to 0, but it still needs to be declared in the CPP file. It's not fully compilable as is...needs headers etc. but was just trying to sketch an idea...
Drew Hall
+5  A: 

I've always thought of randu as the godfather of bad random number generators.

mobrule
Agreed. Randu is a classic.
Boojum
+3  A: 

Implement a fairly short Linear Feedback Shift Register by using bit manipulation in C.

Most of the published material on LFSRs will concentrate on maximal sequences, but it sounds like you could sabotage one of these to produce a shorter sequence, with a little experimentation.

pavium
+1  A: 

A way in which you can introduce clustering while continuing to use gcc is to randomly take two of the returned random numbers as the lower & upper brackets for a random number of iterations. Do this a few times and you should get random clustering.

slashmais
+1  A: 

Use a random number generator (Wikipedia PRNG page), with constraints.

Some other possibilities: UChicago, UMich, FSU

monksy
+2  A: 

The Boost library offers functions to generate random values spread over various non-uniform distributions, including the normal distribution which might generate interesting shaped trees.

Phillip Ngan
A: 

The C standard suggests:

static unsigned long int next = 1;

int rand(void) // RAND_MAX assumed to be 32767
{
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

void srand(unsigned int seed)
{
    next = seed;
}

As a simple linear congruential generator (LCG), it isn't bad (there are many worse sets of constants you could use), but it is certainly not a good pseudo-random number generator compared to other members of the universe of cryptographic and near-cryptographic pseudo-random number generators. It might be bad enough for you, or you could consult Knuth volume 2 to look for other bad sets of numbers. (My (old) copy of Sedgewick has a rather short chapter 35 on random numbers with some illustrations of bad constants.)

Jonathan Leffler
A: 

Take a look at this random function:

http://xkcd.com/221/

Rick
I beleive he was asking for !xkcd :) .."(Oh, any anyone who links to xkcd and/or suggests I just return 4 will get sarcasm in response)."
warren
Soo true, so give me my "will get sarcasm in response"! Downmodding != sarcasm!
Rick
A: 

Chapter 7 of the Numerical Recipes in C book addresses a variety of random number generators. Section 7.7 covers Quasi- (that is, Sub-) Random Sequences.

Andrew
A: 

Often for crappy randomish-looking numbers, and I usually need deterministic ones, I compute sines and cosines of simple expressions with large-ish values and phase modulation. Typically I'm generating colors in two dimensions for graphics purposes ("procedural textures" and all that) so I'll give an example like that in generic pseudocode:

for i=1,N
  for j=1,N
    value[i*n+j] = sin(51*i*i+cos(80*j)) + sin(300*j+3*sin(111*i-j))

Guaranteed to fail most serious tests of randomness. The results are crappy in a way that is useful for art.

It is fun to sit and play with formulas like these in an interactive plotting environment like Matlab or Python with numpy and matplotlib.

DarenW