Looping through a method call too fast? [duplicate] - c#

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
I am calling a method instance called buy. My method randomly generates a string of digits and numbers. My for loop appears to be going to fast for the method to change the string because I get the same string like 2-3 times in a row before getting a new string. when i add a System.Threading.Thread.Sleep(100); I am getting random number like the way it is supposed to be. The problem is that it is way too slow and i feel like there must be a better way. is there a way to get random string each time without invoking the Sleep() method?
for (int i = 0; i < exit; i++)
{
ticket = buy.SetNum();
Console.WriteLine("Wellcome Mr.Nissan. The winning numbers for Lotto max are:");
Console.WriteLine(ticket);
System.Threading.Thread.Sleep(25);
}

Yes, this is a problem with your random number generator - not with the code you posted in the question.
consider the following:
public int GenRandomNum()
{
var r = new Random();
return r.Next()
}
You are generating a new random class based on the same seed if you call it in the same tick, and it will generate the same number. Moving the random initialization out side of the method will fix the problem, like so:
private Random _rand = new Random();
public int GenRandomNum()
{
return _rand .Next()
}

You haven't included the code that actually creates the random number but I suspect you're creating a new instance of the random number generator each time around the loop.
What you need to do instead, is create one instance of the random number generator (outside of the loop) and reuse it for each random number generator .Next() call.

Move the random number generation into into the loop:
var rnd = new Random();
for (int i = 0; i < exit; i++)
{
var ticket = rnd.Next();
Console.WriteLine("Wellcome Mr.Nissan. The winning numbers for Lotto max are:");
Console.WriteLine(ticket);
}
I can't tell you why exactly your posted code wasn't working without seeing the buy.SetNum(); method code.

Related

Why is the random generation and array working together if I press ENTER between each loop? [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 6 years ago.
As long as I have the readkey in the code the end result is 7 different random loops (foreach). When I remove readkey I mostly get 7 identical numbers (foreach).
That led me to start experimenting with Task.Delay but it seems to make no difference. I thought it might be a timing problem as intemittently the first of the 7 random numbers would be different from the last 6.
I want the code to work in one sweep without me having to press a key. My apology if the format in this post is dodgy. I have bad experince of pressing ENTER in this input window.
int[] tray = new int[7];
for (int i = 0; i < tray.Length; i++)
{
Random rnd = new Random();
int randomNumber = rnd.Next(1, 26);
//Task.Delay(9000);
tray[i] = randomNumber;
Console.WriteLine("randomNumber {0} is {1} ENTER ", i + 1, tray[i]);
//Task.Delay(9000);
Console.ReadKey();
}
foreach (var number in tray)
{
Console.WriteLine(number);
}
This is because you are intializing the Random inside the loop. Move the declaration outside of the loop and you should get random values. like:
Random rnd = new Random();
for (int i = 0; i < tray.Length; i++)
{
int randomNumber = rnd.Next(1, 26);
//Task.Delay(9000);
tray[i] = randomNumber;
Console.WriteLine("randomNumber {0} is {1} ENTER ", i + 1, tray[i]);
}
When you have the Random inside the loop, it uses system clock for seed. Without Console.ReadKey each iteration would end up using the same seed because of very less work in the iteration. Thus Random (rnd) would end up using the same seed every time. Once your introduced Console.ReadKey, that will change the seed and because of that you were seeing different result.
One more thing, is that you tried Task.Delay but you didn't see any difference. The reason is that Task.Delay doesn't block the thread, so there was no change in clock time for the next iteration. Just for the purpose of test, you can use :
Task.Delay(1000).Wait();
Or
Thread.Sleep(1000);
This will cause the thread to be blocked for almost a second and you will end up with different/random results.
Still the better approach would be to intialize Random outside the loop.
Task.Delay(9000) does not block. It creates a Task that is completed after (approx.) 9000ms. But you don't wait for that task to complete.
The Random class does not magically generate real random numbers, but takes numbers from a pre-defined pseudo-random number list. Where in the list it starts is depends on a seed passed to its constructor. You use the default constructor which uses a timestamp as seed.
If you don't pause in your loop (via Console.ReadKey() or Thread.Sleep(9000) instead of Task.Delay(9000)), this timestamp is probably always the same so you always get identical "random" numbers.
To avoid these problems, declare your Random outside the loop's scope, so it's initialized once and does not repeat the same numbers:
Random rnd = new Random();
for (int i = 0; i < tray.Length; i++)
tray[i] = rnd.Next(1, 26);
More information about pitfalls in random number generation.
And a (imo) more elegant way to generate an array of 7 random numbers:
Random rnd = new Random();
int[] tray = Enumerable.Range(0, 7).Select(i => rnd.Next(1, 26)).ToArray();

Why doesn't this create a "true" random number? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Random number generator only generating one random number
Im trying to create a loop to create and output 5 random numbers in a listbox. Basically it outputs the same random number 5 times instead of 5 different ones. When I use a break point and go through the code it does actually generate the 5 numbers. So why does it only output the first answer? Thank you. (This is not the entirety of the project, but I need to get this working first).
public string Numbertext1;
public string Numbertext2;
public int GeneratedNumbers;
public int Average = 0;
public int TotalSum = 0;
public int TotalCalcs = 0;
public int Counter = 0;
private void btnRandomise_Click(object sender, EventArgs e)
{
Numbertext1 = txtNum1.Text;
int Number1;
int.TryParse(Numbertext1, out Number1);
Numbertext2 = txtNum2.Text;
int Number2;
int.TryParse(Numbertext2, out Number2);
do
{
Random num = new Random();
int number = num.Next(Number1, Number2);
lbNumbers.Items.Add(Convert.ToString(number));
Counter++;
}
while (Counter < 5);
{
TotalCalcs++;
Counter = 0;
}
}
}
}
You need to initialize your num variable at the global level. It's using the same seed over and over again.
Put this : Random num = new Random(); at the top where you are initializing everything else. Then remove it from inside your method.
It's because you're creating a new Random instance within a tight loop, so the seed number will be the same. The Random class is not truly random (in the mathematical sense), so you should change the seed or use one instance of it. Move Random num = new Random(); to the top with the other variables.
Because you didn't adequately seed the random number generator.
The generator has an algorithmn it follows, if you just create it without seeding it then your numbers will be the same each time. To quote from MSDN:
The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers.
To fix this use the other constructor which allows you to specify a seed - there is a good example of this on MSDN.
The Random class instantiation is time-dependent. With a very quick loop, you're creating the same object every time and thus you're getting the same value over and over. You need to move the instantiation outside the loop so you get new numbers when you call Next() .
This is also the reason why it "works" when you use a break point to check the values. The Random object you created will have different reference times and thus would be different.

same random values [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Random number generator not working the way I had planned (C#)
Why does it appear that my random number generator isn't random in C#?
I have a problem with random values
int weight = 0;
Random random = new Random();
for (int i = 0; i < entriesCount; i++)
{
weight = random.Next(10);
this.weights[i] = weight;
}
This code is in constructor of my object. I create 3 diffrent objects
Object object1 = new Object(2);
Object object2 = new Object(2);
Object object3 = new Object(2);
For every object I get same random values for example: 4, 5 | 4, 5 | 4, 5
Every time I get same values in same sequence. I don`t get why> Please help
Best regards,
Dawid
The problem is that you're creating a new Random each time. When you create an instance of the Random class, it uses the current time as a seed. If you do this multiple times very quickly, you get the same seed value, so the different Random instances output the same results.
In order to work around this, you need to either make sure your random is seeded uniquely each time, or share and use a single Random instance. The easiest option is to just make the Random instance static:
class YourClass
{
private static Random randomGenerator = new Random();
public YourClass(int entriesCount)
{
int weight = 0;
for (int i = 0; i < entriesCount; i++)
{
weight = randomGenerator.Next(10);
this.weights[i] = weight;
}
}
// .. rest of your class
This will cause the class to always reuse the same Random instance, so you'll get different values each time.
Note that if you're going to be using this in a multithreaded scenario, you'll also have to synchronize access to the random instance, or come up with a different approach (such as saving a seed value, and using something like Interlocked.Increment to increment it and seed a new random from each instance, etc).
Random is a pseudorandom number generator, which means the sequence of outputs is the same for any given seed. If you pass a seed to the constructor, you get a different sequence.
As far as I am aware, a random is seeded by the system time unless you specify otherwise. It generates numbers based on this number. As you create them almost exactly at the same time, they have the same seed and will almost always return the same number and sequence.
Any easy fix would be to create a static random all instances share, and just call .Next() on that static object.
From the MSDN documentation:
"using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers."

C# Random codes - Is most of it simply wrong?

I had a lot of issues with randomizing lists. I am talking about a list of 200 elements, where I want to shuffle the list. Don't get me wrong, I read a lot of examples, and on first glance there are pretty nice things, like this:
Randomize a List<T>
But in my experience, at least on a fast machine, this is basically worthless. The shuffling works so fast that there is NOT a MS delay between two calls to Random.NEXT() which results in not nearly random behaviour.
I am NOT talking about super secure stuff, just a basic game random. I know I can add a delay of 1 MS, but this means "wasting" 200 MS just to randomize a list.
Now I found this approach: http://www.codinghorror.com/blog/2007/12/shuffling.html
It looks nice, using GUIDs to sort. BUT aren't they created the same way? Lets step it up a notch, lets assume I want to create 1000 numbers, between 0 - 5. This code is basically useless:
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultA.Add(new Random().Next(5));
}
var resultB = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultB.Add(new Random().Next(5));
Thread.Sleep(1);
}
A does not work at all, at least not im my environment in Windows Phone 7. B is fine, but it takes a second, which is also stupid. Any comments or thoughts, it can't be that hard to create a random list of integers :-)
Don't keep initializing a new instance of Random; make just one and continually reference it.
var random = new Random();
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultA.Add(random.Next(5));
}
You are correct that repeatedly creating new instances of Random within the same "timestamp" will result in the same seed; but calling .Next on an instance of Random "advances" the seed so that the next number you retrieve is (most likely) different.
This is also covered in the documentation on Random:
... because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.
...
This problem can be avoided by creating a single Random object rather than multiple ones.
You need to keep hold of the same instance of Random.
var random = new Random();
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultA.Add(random.Next(5));
}
var resultB = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultB.Add(random.Next(5));
Thread.Sleep(1);
}
This is because when Random initializes it uses the system clock to get a point in time. When you call next it can use the difference in time to get the next number. If you keep initializing a Random object you will keep getting the same number most of the time.
The shuffling works so fast that there is NOT a MS delay between two calls to Random.NEXT() which results in not nearly random behaviour.
What makes you think that there needs to be a ms delay between two calls to Random.Next?
Your bog standard random number generator is going to take some initial seed (say the system clock) and then repeatedly some algorithm to that seed to produce a sequence of numbers that appears to be random. Most of these algorithms don't take the clock as an input other than for the seed and so it doesn't matter how quickly two consecutive calls are executed.
The reason your code fails is because you keep instantiating a new random number generator on each iteration. This is where the clock can kill you because you end up with the same seed twice. You are not calling Random.Next consecutively on the same random number generator. You are calling Random.Next on a new random number generator on every iteration and sometimes these random number generators are seeded with the same value because you are seeding them by the system clock.
Move the instantiation of the random number generator outside of your loop.
var resultA = new List<int>();
Random rg = new Random();
for (int i = 0; i < 1000; i++) {
resultA.Add(rg.Next(5));
}

C# code only gives expected results on step through?

Ok so I have a dice throw app...
When I step through the code it functions normally and 'results' contains the correct number of throw results and they appear to be random, when I leave the code to run and do exactly the same thing it produces a set of identical numbers.
I'm sure this is a logical error I cannot see but fiddling with it for hours hasnt improved the situation, so any help is much appriciated. :)
class Dice
{
public int[] Roll(int _throws, int _sides, int _count)
{
Random rnd = new Random();
int[] results = new int[_throws];
// for each set of dice to throw pass data to calculate method
for (int i = 0; i < _throws; i++)
{
int thisThrow = Calculate(_sides, _count);
//add each throw to a new index of array... repeat for every throw
results[i] = thisThrow;
}
return results;
}
private int Calculate(int _sides, int _count)
{
Random rnd = new Random();
int[] result = new int[_count];
int total = 0;
//for each dice to throw put data into result
for (int i = 0; i < _count; i++)
{
result[i] = rnd.Next(1, _sides);
}
//count the values in result
for (int x = 0; x < _count; x++)
{
total = total + result[x];
}
//return total of all dice to Roll method
return total;
}
}
First mistake: Never use multiple instances of Random, use a single instance, and pass that along with the other parameters.
When you create "Random rnd = new Random();" it is seeded by the current time. When you debug your code (which takes time) it will be seeded differently each time.
Create 1 instance of Random, and reference that everywhere.
You're creating a random class every time you need to create a number. Doing this will give you the nutty results.
See here: FROM MSDN
This problem can be avoided by creating a single Random object rather than multiple ones.
To improve performance, create one Random object to generate many random numbers over time, instead of repeatedly creating a new Random objects to generate one random number.
E.g. create a private instance of Random...
In addition to what has been mentioned before...
Use Random for things like dice, card games, choosing random images and so forth. If you ever need to create a random number for security sake, use System.Security.Cryptography.RandomNumberGenerator. This simple example shows creating a random integer.
RandomNumberGenerator gen = RandomNumberGenerator.Create();
byte[] myBytes = new byte[4];
gen.GetBytes(myBytes);
int myValue = (BitConverter.ToInt32(myBytes, 0));
DO NOT use this unless you have a security need. The performance is less than that of the Random class. I suppose you could use this to seed Random but that might be overkill.
EDIT: It occurred to me that I had never tested this. A quick performance test showed the following:
1,000,000 random numbers:
RandomNumberGenerator: 2.6 seconds
Random: .015 seconds.
So Random is about 150 times faster.
Give the constructor Random a seed. That's the problem.
http://msdn.microsoft.com/en-us/library/aa329890%28VS.71%29.aspx
Random r = new Random(DateTime.Now.Millisecond);

Categories

Resources