Code For Random not working properly [duplicate] - c#

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
I am creating a random function to give me four random values of A,B,C,D and the sign(+,-). The problem is the code generates all same values and the output I get has only A=B=C=D=x where x is any random value generated by the code. Also I tried to put a breakpoint and debug it, it works just fine no problems but as soon as I remove the break point the same issue occurs. Can anyone please tell me where am I going wrong. The code is as follows:
public void RandomQuestionGenerate()
{//all the variables(A,B,C,D,sign1,sign2) are globally defined
Random FirstNo = new Random();
A = FirstNo.Next(0, 10);
Random SecondNo = new Random();
TextA.Text = A.ToString();
B = SecondNo.Next(0, 10);
Random ThirdNo = new Random();
TextB.Text = B.ToString();
C = ThirdNo.Next(0, 10);
Random FourthNo = new Random();
TextC.Text = C.ToString();
D = FourthNo.Next(0, 10);
TextD.Text = D.ToString();
Random FirstSign = new Random();
int x = FirstSign.Next(0, 2);
if(x == 0)
{
Sign1 = "+";
}
else if(x == 1)
{
Sign1 = "-";
}
TextSign1.Text = Sign1;
Random SecondSign = new Random();
int y = SecondSign.Next(0, 2);
if (y == 0)
{
Sign2 = "+";
}
else if (y == 1)
{
Sign2 = "-";
}
TextSign2.Text = Sign2;
}

You should have only one instance of Random, preferably for your entire program.
Random is automatically seeded with a time-based value when you create it using the default constructor:
Initializes a new instance of the Random class, using a time-dependent default seed value.
https://msdn.microsoft.com/en-us/library/h343ddh9(v=vs.110).aspx
The problem is, you are creating those four instances faster than the resolution of this time-based value. So all four instances are being seeded with the same value. And when called with the same parameters, each will return the same value.
Because of race conditions like this, you should keep just one global instance of Random if possible.

Use one instance and call .Next. Your issue is the seed for all of those Random instances is coming out the same (it defaults to a time-based seed).
The implementation is just an algorithm that requires a starting value to begin deriving other "random" values from. It isn't at all random, you can figure out what the value will be knowing the seed and the algorithm used.

Don't create a new Random instance every time.
Keep a single Random instance and call Next() for every new random number.
See this SO question for more details.

Related

Looping through a method call too fast? [duplicate]

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.

list of random objects from another list c# [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Select N random elements from a List<T> in C#
(34 answers)
Closed 8 years ago.
I have a list private List<HeroStats> allHeroes;
and a list private List<Team> allTeams;
After I populate my list 'allHeroes' with heroes , I want to create teams of 5 random heroes, using this method:
public Team createTeam()
{
int index=0;
Team t = new Team();
Random rnd = new Random();
int cap = allHeroes.Count;
while (t.count() < 5)
{
index = rnd.Next(0, cap);
t.Add(allHeroes.ElementAt(index));
}
return t;
}
This creates a perfect team , but if i want to create more teams, it will generate the same team over and over again.
I also have a method
public List<HeroStats> print()
{
StringBuilder sb = new StringBuilder();
List<HeroStats> l = new List<HeroStats>();
foreach (HeroStats h in team)
{
sb.AppendLine(h.HeroName);
l.Add(h);
}
Console.WriteLine(sb.ToString());
return l;
}
Which should print out the name of the heroes in a team.
Why am I getting the same team if I generate many ?
To create multiple teams I use :
Team a = new Team();
for (int i = 0; i < 2000; i++)
{
a = createTeam();
allTeams.Add(a);
}
It is creating the same teams because the Random instance is created in the method which is causing the same seed if you call createTeam very fast (the default Random constructor uses the current time as seed). You can avoid that either by passing the Random to the method or by using a field:
public Team createTeam(Random rnd) // as an aside, you should call it CreateRandomTeam
{
int index=0;
Team t = new Team();
int cap = allHeroes.Count;
while (t.count() < 5)
{
index = rnd.Next(0, cap);
t.Add(allHeroes.ElementAt(index));
}
return t;
}
Now you have to ensure that you pass always the same Random instance to createTeam.
For example with your loop:
Random rnd = new Random();
Team a = new Team();
for (int i = 0; i < 2000; i++)
{
a = createTeam(rnd);
allTeams.Add(a);
}
MSDN also mentions this in the remarks section:
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. This problem can be avoided by using a single
Random object to generate all random numbers. You can also work around
it by modifying the seed value returned by the system clock and then
explicitly providing this new seed value to the Random(Int32)
constructor
You need to have
Random rnd = new Random();
Outside of
public Team createTeam()
{
}
Maybe parse in the rnd as a parameter.
From the documentation of Random
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.
If you are calling createTeam() in a tight loop to create your random teams, you will end up with the same set of random numbers due to the fact that your instances of Random are create so close to each other and with the same seed.
A possible solution is to take out the object of type Random and make it a class level field.
public static class RandomTeamCreator
{
private static readonly Random _random = new Random();
public Team CreateTeam()
{
// create team using _random
}
}
Why am I getting the same team if I generate many ?
Probably because the time between creating teams is not enough for the internal clock to create a new random seed.
I would add a "seed" parameter to createTeam:
public Team createTeam(int seed)
{
int index=0;
Team t = new Team();
Random rnd = new Random(seed);
int cap = allHeroes.Count;
while (t.count() < 5)
{
index = rnd.Next(0, cap);
t.Add(allHeroes.ElementAt(index));
}
return t;
}
And then use another Random outside of th eloop to generate the seed:
for(int 1 = 0; i < 10; i++)
{
Random r = new Random(0);
int seed = r.Next();
createTeam(int seed);
}
If you wanted to keep the original signature just add an overload:
public Team createTeam()
{
return createTeam(new Random().Next());
}
SIDE NOTE
You _probably want a "shuffled" team of heroes rather than a "random" since with "random" you could get the same hero twice. If that is the case then just use an "order by" with a random order:
public Team createTeam(int seed)
{
Random rnd = new Random(seed);
Team t = new Team();
var shuffled = allHeroes.OrderBy(rnd.Next()).Take(5);
foreach(var hero in shuffled)
t.Add(hero);
return t;
}
If you create many Random instances at roughly the same time, they are likely to generate the same numbers. Instead, create one Random somewhere else and call its Next method from your algorithm.

How to use the C# random method most effectively? [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
I have been able to use the random method to accomplish most of my tasks in trying to populate labels and RadioButtonList Items randomly to create a 5 question quiz.
The code generates a good blend of questions given the large pool it draws from.
However, the inner code for randomly populating the RadioButtonList Items is acting funny.
When I throw in breakpoints at my while loop and run it step by step the answers are populated in different order on every next question.
But when I simply open up the browser and run it from the Sharepoint website I have it deployed to,
the answers follow the same order sequence on every next question/all questions.
Note: It does however throw unique orders on page refresh; in other words when I start the quiz again.
I cant seem to figure out the hitch for the life of me.
Could use a few sets of eyes.
Here is the code thus far: Please advise
public void LoadQuestions()
{
try
{
SPWeb thisWeb = SPContext.Current.Web;
SPList oSPList = thisWeb.Lists["QuestionsAndAnswers"];
SPListItemCollection oSPListItemCollection = oSPList.Items;
Random rand = new Random();
List<int> tempStore = new List<int>();
List<int> tempStore2 = new List<int>();
int tempValue = 0;
//int tempValue2 = 0;
int icount = 1;
int iMax = oSPListItemCollection.Count;
//int icount2 = 0;
//int iMax2 = oSPListItemCollection.Count;
SPListItem thisItem;
Label thisQuestion;
Label thisCorrectAnswer;
RadioButtonList thisAnswers;
while (icount < 6)
{
tempValue = rand.Next(1, iMax);
if (tempStore.Exists(value => value == tempValue))
continue;
else
{
tempStore.Add(tempValue);
thisQuestion = (Label)UpdatePanelMaster.FindControl("Question" + icount.ToString());
thisItem = oSPListItemCollection[tempValue];
thisQuestion.Text = icount + ". " + thisItem["Question"].ToString();
thisCorrectAnswer = (Label)UpdatePanelMaster.FindControl("CorrectAnswer" + icount.ToString());
thisCorrectAnswer.Text = thisItem["CorrectAnswer"].ToString();
thisAnswers = (RadioButtonList)UpdatePanelMaster.FindControl("RadioButtonList" + icount.ToString());
//Entering code to handle random answer arrangements
//This code works ok when run in a step by step debug fashion but no when deployed and run from the website directly.
Missing/Changes required?
int tempValue2;
int Icounter = 0;
string[] AnswerArr = new string[] { thisItem["CorrectAnswer"].ToString(), thisItem["IncorrectAnswer1"].ToString(), thisItem["IncorrectAnswer2"].ToString(), thisItem["IncorrectAnswer3"].ToString() };
Random rand2 = new Random();
while (Icounter < 4)
{
tempValue2 = rand2.Next(0, 13);//max number of items in the array
decimal toCeilingVar = tempValue2 / 4;
int fraction = Convert.ToInt32(System.Math.Ceiling(toCeilingVar));
string tempArrValue = AnswerArr[fraction];
if (thisAnswers.Items.FindByValue(tempArrValue) == null)
{
//add new value because the current value is not in the list
thisAnswers.Items.Add(tempArrValue);
Icounter++;
tempArrValue = string.Empty;
}
tempValue2 = 0;
toCeilingVar = 0;
fraction = 0;
//End Random Answer handling
}
tempValue = 0;
icount++;
}
}
}
//End random question handling
catch (Exception ex)
{
throw ex;
}
}
The problem is (inside the loop):
Random rand2 = new Random();
The Random class is, if no explicit seed is provided, seeded using the time. If you create multiple instances in a tight loop, they will often be close enough (in time) together that they have the same seed. This means they will all generate the same sequence of pseudo-random numbers. Two options:
lose the inner Random instance (rand2) completely - just use the single outer instance (rand); using more Random instances does not increase the randomness
use the outer instance to seed the inner instance
I'd only use the latter if there was a good reason, for example parallelism
Probably what is happening here is that when run in production, the line Random rand2 = new Random() is called several times in a very short interval of time, so each instance will have the same initial seed value. The default constructor for Random uses a time-based seed with fairly low resolution in my experience.
To solve this, I would just use the single rand variable to generate all random numbers, or initialize rand2 outside the outermost loop.

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.

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