Calling a Random Number Generating Member Function Doesn't Produce Entirely Random Numbers

Calling a random number generating member function doesn't produce entirely random numbers

The issue here is that you constantly recreate and seed the random number generator in rand_node_colour. You call it in a tight loop so you can get the same time which means the seed will be the same and that means the random numbers generated will be the same.

What you need to do is seed the generator once and then keep using its random output. An easy way to fix you code would be to make it static in the function sos it is only initialized once and each subsequent call to the function will continue on instead of start the generator all over. If we do that the code becomes

void rand_node_colour(int nodeWeights[])
{
// construct a trivial random generator engine from a time-based seed:
static std::default_random_engine generator (std::chrono::system_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> distribution(0,255);
for(int i=0; i<3; i++)
{
nodeWeights[i] = distribution(generator);
}
}

Random Number Generator - not generating a random number every time

Pseudo-random generators will generate the same sequence of "random" numbers for the same seed.

You are repeatedly seeding the generator with the time in seconds. You're doing it 5 times very quickly. So the time is always the same for each iteration. Hence you get the first number of said sequence and it'll always be the same.

C++ random function gives the same integers twice as output

You're repeatedly reseeding with time(0) which only has second-level granularity, so as long as the code doesn't cross a second boundary, you're always seeding with the same value.

Make your engine once, and reuse it instead of reseeding over and over. The simplest solution would be to just change:

std::default_random_engine randomGenerator(time(0));

to:

static std::default_random_engine randomGenerator(time(0));

which initializes a single global copy once, and reuses it without reseeding. This is fine if you don't need crypto grade randomness, just something "randomish".

Better solutions involve using std::random_device to produce seed (though sadly, the C++ standard doesn't require it to be implemented with cryptographic randomness, so it's surprisingly difficult to do this properly and portably with any guarantees on behavior).

Why does it appear that my random number generator isn't random in C#?

The problem with min = 0 and max = 1 is that min is inclusive and max is exclusive. So the only possible value for that combination is 0.

Random number generator only generating one random number

Every time you do new Random() it is initialized using the clock. This means that in a tight loop you get the same value lots of times. You should keep a single Random instance and keep using Next on the same instance.

//Function to get a random number 
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}

Edit (see comments): why do we need a lock here?

Basically, Next is going to change the internal state of the Random instance. If we do that at the same time from multiple threads, you could argue "we've just made the outcome even more random", but what we are actually doing is potentially breaking the internal implementation, and we could also start getting the same numbers from different threads, which might be a problem - and might not. The guarantee of what happens internally is the bigger issue, though; since Random does not make any guarantees of thread-safety. Thus there are two valid approaches:

  • Synchronize so that we don't access it at the same time from different threads
  • Use different Random instances per thread

Either can be fine; but mutexing a single instance from multiple callers at the same time is just asking for trouble.

The lock achieves the first (and simpler) of these approaches; however, another approach might be:

private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());

this is then per-thread, so you don't need to synchronize.

How to reference random generator?

You should seed a random number generator only once. Other than that, your getRandom function is correct. As for how to use all this in a class context, here's how you could do it:

#include <random>

class RNG
{
public:
RNG::RNG() : gen(std::random_device()()) {} // Seeds the mt19937.

double getRandom(Object* foo){
std::uniform_real_distribution<double> dis(0, foo->limit);
double random = dis(gen);
return random;
}

private:
std::mt19937 gen;
};

So at the the start of the program, you instantiate one RNG, and the mt19937 will be seeded once. Then you just call getRandom on that same RNG whenever you need a random number.

Generating random whole numbers in JavaScript in a specific range

There are some examples on the Mozilla Developer Network page:

/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}

/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}

Here's the logic behind it. It's a simple rule of three:

Math.random() returns a Number between 0 (inclusive) and 1 (exclusive). So we have an interval like this:

[0 .................................... 1)

Now, we'd like a number between min (inclusive) and max (exclusive):

[0 .................................... 1)
[min .................................. max)

We can use the Math.random to get the correspondent in the [min, max) interval. But, first we should factor a little bit the problem by subtracting min from the second interval:

[0 .................................... 1)
[min - min ............................ max - min)

This gives:

[0 .................................... 1)
[0 .................................... max - min)

We may now apply Math.random and then calculate the correspondent. Let's choose a random number:

                Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)

So, in order to find x, we would do:

x = Math.random() * (max - min);

Don't forget to add min back, so that we get a number in the [min, max) interval:

x = Math.random() * (max - min) + min;

That was the first function from MDN. The second one, returns an integer between min and max, both inclusive.

Now for getting integers, you could use round, ceil or floor.

You could use Math.round(Math.random() * (max - min)) + min, this however gives a non-even distribution. Both, min and max only have approximately half the chance to roll:

min...min+0.5...min+1...min+1.5   ...    max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max

With max excluded from the interval, it has an even less chance to roll than min.

With Math.floor(Math.random() * (max - min +1)) + min you have a perfectly even distribution.

 min...  min+1...    ...      max-1... max....   (max+1 is excluded from interval)
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max

You can't use ceil() and -1 in that equation because max now had a slightly less chance to roll, but you can roll the (unwanted) min-1 result too.



Related Topics



Leave a reply



Submit