Random Number Generator Only Generating One Random Number

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.

C# random number generator still gives same number each time

I've tried putting an instance of random outside the loop and then
calling it from inside the loop but this has caused an exception

Here are two concrete examples, one for a Console app, and the other for a WinForms app.

This is one way to declare it in a Console app. random can be used from anywhere within the application, even in methods other than Main():

class Program
{

private static Random random = new Random();

static void Main(string[] args)
{
// ... code ...

for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
int randomNumber = random.Next(1, 50);

personalNumbers[i] = randomNumber.ToString();
}

// ... code ...
}

}

This is one way to declare it for use in a WinForms app. random in this example can be used anywhere within Form1:

public partial class Form1 : Form
{

private Random random = new Random();

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
// ... code ...

for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
int randomNumber = random.Next(1, 50);

personalNumbers[i] = randomNumber.ToString();
}

// ... code ...
}

}

This should cover most simple homework assignments. Nothing fancy here.

Random number generation giving same numbers few times consecutively

You'll need to track the previous number and compare it to the current one:

int? lastNum = null; // variable for tracking the last generated number
// I've chosen a nullable int since it will cover any random number range
for(int i=0;i<100;i++)
{
int num = 0;
do
{
num = random.Next(5);
}
while (lastNum.HasValue && num == lastNum.Value); // if the lastNum was set and is the same value, loop and generate a new number
lastNum = num; // store the last value for the next iteration.

Console.WriteLine(num);
}

Of course you could still end up with a sequence like 40142434, etc. but that's life.

Why does Random.Next() always return the same number

You're always seeding a new instance with the same seed, and then grabbing the first max. By using a Seed, you're guaranteeing the same results.

If you want to have a static, random number generation that does different results, you should rework this a bit. However, since Random is not threadsafe, it requires some synchronization when used statically. Something like:

private static Random random;
private static object syncObj = new object();
private static void InitRandomNumber(int seed)
{
random = new Random(seed);
}
private static int GenerateRandomNumber(int max)
{
lock(syncObj)
{
if (random == null)
random = new Random(); // Or exception...
return random.Next(max);
}
}

Why is my C code only generating every third random number?

Converting comments into an answer.

What is RAND_MAX on your system? If it is a 15-bit or 16-bit value, you probably aren't getting good enough quantization when converted to double. If it is a 31-bit or bigger number, that (probably) won't be the issue. You need to investigate what values are generated by just the rand01() function with different seeds, plus the multiplication and cast to integer — simply print the results and sort -n | uniq -c to see how uniform the results are.

On my system RAND_MAX is only 32767. Do you think that might be why my results might not be granular enough? Now that you've made me think about it, there would only be 32,767 possible values and my network array is 100,000 possible values. Which corresponds about about the 1/3 results I am getting.

Yes, I think that is very probably the problem. You want 100,000 different values, but your random number generator can only generate about 33,000 different values, which is awfully close to your 1:3 metric. It also explains immediately why you got good results when you reduced the multiplier from 100,000 to 10,000.

You could try:

double rand01(void)
{
assert(RAND_MAX == 32767);
return ((rand() << 15) + rand()) / ((RAND_MAX + 1.0) * (RAND_MAX + 1.0));
}

Or you could use an alternative random number generator — for example, POSIX defines both the drand48() family of functions and
random(), with corresponding seed-setting functions where needed.

Using a single set of random number generators in a loop

that will "restart" at the beginning of the set for every iteration of i

was thinking of using random numbers with seeds somehow but haven't been able to figure it out.

Code could abuse srand()

// Get some state info from rand() for later.
unsigned start = rand();
start = start*(RAND_MAX + 1u) + rand();

for(int i = 0; i < N; i++) {
// Initialize the random number generator to produce the same sequence.
srand(42); // Use your favorite constant.
for(int j = 0; j < M; j++) {
x = sampleNormal();
y = sampleNormal();
t = j/fsamp;

a = x*cos(2*pi*f*t)+y*sin(2*pi*f*t);
}
}

// Re-seed so other calls to `rand()` are not so predictable.
srand(start);


Related Topics



Leave a reply



Submit