This question already has answers here:
Instantiating Random in or out of the loop
(7 answers)
Closed 2 years ago.
I'm getting some very strange behavior, please help!
I'm iterating through an object array, the participate property is a bool. The method randomly assigns each person a true or false (50/50 right now).
As the code is right now, all five people either get all true or all false.
When the message box is enabled, the code works properly (each person gets a true or false, not all the same)!!!!
for (int i = 0; i < 5; i++)
{
//other code removed, I'll add it if it turns out to be important to the problem
person[i].participate = doesPersonJoin();
}
public bool doesPersonJoin()
{
bool joinBool = true;
Random rnd = new Random();
int r = rnd.Next(1, 100);
//MessageBox.Show(r.ToString());
if (r > 50)
{
joinBool = false;
}
return joinBool;
}
The random number generator works by setting a seed value based by default on the current clock time. Without MessageBox, the code runs so fast all of the random instances have the same seed and therefore produce the same value when .Next() is called.
To fix this, you should create ONE random instance you can use throughout your program, or at least one instance (possibly static) for use in that class.
Related
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
This is really weird, and I cannot see why this is happening. In the foreach cycle, I am iterating through a class A collection, and for each class, I call the Count() method, where r1 and r2 numbers are generated from range [-1,1]. The problem is that Random.Next returns the same "random" numbers for each instance. When the results for the first instance are 0 and -1, the same ones will be returned from following instances. Please, could you tell me why this is happening? Also, I cannot get different results in each class A instance. This is the code:
class a
{
Random rnd = new Random();
private void Count()
{
int r1 = rnd.Next(-1, 1);
int r2 = rnd.Next(-1, 1);
}
}
class b
{
List<a> listofA=new list<a>();
foreach (a ACLASS in listofA)
{
ACLASS.Count();
}
}
The problem is that you are creating instances of the Random class too close in time.
When you create a Random object, it's seeded with a value from the system clock. If you create Random instances too close in time, they will all be seeded with the same random sequence.
Create a single Random object and pass its reference to the constructor when you create instances of the "a" class, instead of creating one Random object for each "a" instance.
Use a single, static Random number generator for all instances of the class.
class a
{
private static Random rnd;
static a() {
rnd = new Random();
}
private void Count()
{
int r1 = rnd.Next(-1, 2);
int r2 = rnd.Next(-1, 2);
}
}
Note the change to give you numbers in the range -1,1 rather than -1,0
You're creating new instances of Random very close together (your loop is very tight) so each instance is effectively using the same seed value.
A better approach would be to create one instance and pass that to your Count method.
You probably know this next bit, but I'll include it here for completeness:
The MSDN has the details on this, but basically your problem is the Random.Next method you're using generates:
A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.
because of this your calls will return -1 or 0.
You include a random instance for each A instance. It sounds like they're all getting the same default seed value. You probably want to make a static random for all A instances and use it repeatedly, or alternatively provide a seed value to the Random() instance in the A constructor.
This question already has answers here:
How can I capture the value of an outer variable inside a lambda expression?
(4 answers)
Closed 6 years ago.
What is going on here? This loop most of the time just prints this:
10101010101010101010
sometimes this:
51010101010101010101
and when i debug it, it prints in order
0123456789
class Program
{
static void Main (string[] args)
{
for ( int i = 0; i < 10; i++)
{
Task.Run(( ) => Console.Write(i));
}
Console.Read();
}
}
If you have ReSharper installed it puts a little squiggle underneath the i:
with the note:
Access to modified closure
The JetBrains site gives this explanation:
This may appear to be correct but, in actual fact, only the last value of str variable will be used whenever any button is clicked. The reason for this is that foreach unrolls into a while loop, but the iteration variable is defined outside this loop. This means that by the time you show the message box, the value of str may have already been iterated to the last value in the strings collection.
(obviously their example uses a string not an int).
It "works" under debug because other things are going on and the code isn't being executed the same as it would in release.
The solution is to use a local variable:
for ( int i = 0; i < 10; i++)
{
int local = i;
Task.Run(( ) => Console.Write(local));
}
But even then it's not guaranteed to execute in the order you expect. I just tested this and got he result:
0436215897
So each value was processed, but in indeterminate order.
I am having weird problem with the code below where when I exclude breakpoints from my while loop, the results are different.
The foreach loop, loops through 20 items from a list and adds each item to a dictionary.
When I add a breakpoint in the loop and skip through 20 times, 20 items are added.
If I remove all breakpoints and run the program only 1 item is added.
public void AddLinks(Dictionary<Guid,string> RowKeyTitles)
{
var combinedUrlsList = new Dictionary<string, string>();
var urlTemplate = ConfigurationManager.AppSettings["playlisturl"];
var count = 0;
foreach (var row in RowKeyTitles)
{
var shortUrl = StringGenerator.GenerateShortLink(4);
var combinedUrl = urlTemplate.Replace("{name}", row.Value).Replace("{id}",row.Key.ToString());
while (!combinedUrlsList.ContainsKey(shortUrl))
{
Console.WriteLine("test");
shortUrl = StringGenerator.GenerateShortLink(4);
if (!combinedUrlsList.ContainsKey(shortUrl))
{
count++;
Console.WriteLine("Added{0}", count);
combinedUrlsList.Add(shortUrl, combinedUrl);
}
}
}
Console.WriteLine("Count{0}",combinedUrlsList.Count());
Console.ReadLine();
}
Does anyone knows what could be causing this behavior?
I will make a guess and say that StringGenerator.GenerateShortLink(4); generates the same shortUrl in a tight loop. This is most probably, you are creating a new Random class in the loop.
An example for broken code
while(.....)
{
Random rnd = new Random();
rnd.Next();
}
This would generate many same numbers, since Random() uses system time as a seed.
To fix. declare Random as a your class's private field and create it only once.
The only possible explanation with the information given is that StringGenerator.GenerateShortLink is implemented in a way that it is "timinig-sensitive" - for example if it uses a Random instance internally and recreates it at every call... in such a case the newly created instance (by default) is initialized utilizing the current system time... with breakpoints it gets delayed enough that it produces a different random number... without breakpoints it gets initialized with the same number (because there is not enough delay) and thus produces the same random number(s) which in turn produces the same shortUrl it already produced the first time... since that is already part of the Dictionary combinedUrlsList it just won't be added a second time...
Fix for the above behaviour:
Don't recreate the Random instance used inside StringGenerator.GenerateShortLink between calls but reuse the already created instance in subsequent calls...
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 6 years ago.
I have a class:
public class MyClass
{
public int MyMethod()
{
Random rand = new Random();
return rand.Next() % 10 + 1;
}
}
And 2 objects of it:
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
The problem is that obj1.MyMethod() == obj2.MyMethod() always. Why does it happen? What's the best way to avoid it?
Create your random object static
public class MyClass
{
public static Random rand = new Random();
public int MyMethod()
{
return rand.Next() % 10 + 1;
}
}
Random works on System.DatTime.Now.Ticks.
If we do like this
Random rand = new Random();
internally it happens as
Random rand = new Random(System.DateTime.Now.Ticks);
Just think for a moment the only thing which is not constant in system is System Time.
When ever using Random class make its object once and use its method Next() where ever you want. You will find this situation in loops when random object is created inside loops.
In your code they are created one after another, they get created by same Ticks seed value.
Create your random object static and then they won't be same.
you are creating a new Random every time. When you create a new instance of Random without explicitly specifying the seed value it uses System.DatTime.Now.Ticks as the seed. Due to the speed of calls they are happening at the same 'Tick' so the same seed value is used. As all Random instances generate the exact same sequence of 'random' number for the same seed value the same 'random' value is generated by both instances.
This has been covered many times before on the site and you should search for one of those answers.
But basically you need to create your Random object once and reuse it. This could be done statically , or at least as a class variable.
You should read this question and its answers to find a better approach.
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
This is really weird, and I cannot see why this is happening. In the foreach cycle, I am iterating through a class A collection, and for each class, I call the Count() method, where r1 and r2 numbers are generated from range [-1,1]. The problem is that Random.Next returns the same "random" numbers for each instance. When the results for the first instance are 0 and -1, the same ones will be returned from following instances. Please, could you tell me why this is happening? Also, I cannot get different results in each class A instance. This is the code:
class a
{
Random rnd = new Random();
private void Count()
{
int r1 = rnd.Next(-1, 1);
int r2 = rnd.Next(-1, 1);
}
}
class b
{
List<a> listofA=new list<a>();
foreach (a ACLASS in listofA)
{
ACLASS.Count();
}
}
The problem is that you are creating instances of the Random class too close in time.
When you create a Random object, it's seeded with a value from the system clock. If you create Random instances too close in time, they will all be seeded with the same random sequence.
Create a single Random object and pass its reference to the constructor when you create instances of the "a" class, instead of creating one Random object for each "a" instance.
Use a single, static Random number generator for all instances of the class.
class a
{
private static Random rnd;
static a() {
rnd = new Random();
}
private void Count()
{
int r1 = rnd.Next(-1, 2);
int r2 = rnd.Next(-1, 2);
}
}
Note the change to give you numbers in the range -1,1 rather than -1,0
You're creating new instances of Random very close together (your loop is very tight) so each instance is effectively using the same seed value.
A better approach would be to create one instance and pass that to your Count method.
You probably know this next bit, but I'll include it here for completeness:
The MSDN has the details on this, but basically your problem is the Random.Next method you're using generates:
A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.
because of this your calls will return -1 or 0.
You include a random instance for each A instance. It sounds like they're all getting the same default seed value. You probably want to make a static random for all A instances and use it repeatedly, or alternatively provide a seed value to the Random() instance in the A constructor.