This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
I have an array of strings that I want to pick one variable randomly from the list. Although I am using random function but I would like to know whether it will pick value zero ever or not? (Element zero from my array)
string randomString = a[new Random().Next(a.Length)];
Random should be random, so getting an A should be Random
One thing to note is if you're calling
string randomString = a[new Random().Next(a.Length)];
in quick succession e.g. in a loop, then create a class field, else Next() will be the same.
private Random _random = new Random();
then in your function call
string randomString = a[_random.Next(a.Length)];
The Random class simply uses pseudorandom number generation to give you a number that fits your specifications and seems random. Your code is fine, but with (in theory) 26 possible results, getting one of them shouldn't occur too often.
I believe the issue you're experiencing is that you're creating new Random objects in a loop, and they're ending up with the same seed, try declaring it in your class:
Random rnd = new Random();
And using it like so:
string randomString = a[rnd.Next(a.Length)];
The benefit of using this (as opposed to your current method) is that if you run it inside a loop you don't risk getting the same answer multiple times in a row.
Hope this helped, cheers!
~Winderps
How can you say rarely?
try this:
String[] myArray = new String[] { "A", "B", "C" };
Random rd = new Random();
Int32 aCounter = 0;
Int32 bCounter = 0;
Int32 cCounter = 0;
for (int i = 0; i < 25000; i++)
{
Int32 retVal = rd.Next(myArray.Length);
switch (retVal)
{
case 0:
aCounter++;
break;
case 1:
bCounter++;
break;
case 2:
cCounter++;
break;
}
}
As expected in my test, as expected aCounter, bCounter and cCounter always have same values between 8000 and 8500.
Perahps you called your new Random().Next() too soon use a single object Random and call Next() each time on the same object
Related
This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 6 years ago.
I can't understand what's wrong.
static int WinningColumn()
{
Random rnd = new Random(46);
int[] winningnumbers = new int[6];
int[] Check = new int[46];
int i;
for (i = 0; i < winningnumbers.Length; i++)
{
winningnumbers[i] = rnd.Next(46);
Check[winningnumbers[i]]++;
if (Check[winningnumbers[i]] > 1)
{
i--;
continue;
}
The error happens here:
}
return winningnumbers[i];
}
When you exit from the for loop the indexer variable i has a value bigger than the max index possible (It is the condition that breaks the loop).
In your case the variable i has the value of 6 but the max index possible for the array winningnumbers is 5. (0 to 5 are six integer elements).
It is not clear what is your intent but supposing that your purpose is to generate six winning numbers ranging from 0 to 45 then your code should be rewritten and simplified in this way
static List<int> WinningColumn()
{
// Do not initialize Random with a fixed value
// You will get always the same 'random' sequence
Random rnd = new Random();
// Create a list to store the winners
List<int> winningnumbers = new List<int>();
int i = 0;
while(i < 6)
{
int newNumber = rnd.Next(46);
if(!winningnumbers.Contains(newNumber))
{
// If the list doesn't contain the number the add it and increment i
// Otherwise run the loop again....
winningnumbers.Add(newNumber);
i++;
}
}
// This returns the whole list to the caller,
// you can use it as an array
return winningnumbers;
}
Notice that your actual code contains a bug in the declaration of the Random number generator. You pass an initial seed and thus, everytime you call this method, the random generator starts again with the same sequence of numbers. The result would be an identical list of numbers. Not very random to me
If you don't pass anything then the generator is initialized with the system time and thus should be different every time you call this method.
I don't know what you want to achieve here.
But the loop would terminate when i becomes 6.
So you are basically trying to access winningnumbers[6] which is incorrect since winningnumbers array has length 6 so you can use index from 0 till 5.
You may try with winningnumbers [i-1]
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
Consider this method:
private static int GenerateRandomNumber(int seed, int max)
{
return new Random(seed).Next(max);
}
On my machine, executing this loop yields the same number through 1500 iterations:
for (int i = 0; i < 1501; i++)
{
int random = GenerateRandomNumber(100000000, 999999999);
Console.WriteLine(random.ToString());
Console.ReadKey();
}
I get 145156561, for every single iteration.
I don't have a pressing issue, I was just curious about this behavior because .Next(max) says "Returns a Non Negative random number less than the specified maximum. Perhaps I am not understanding something basic.
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);
}
}
Dilbert has encountered the same problem back in 2001:
http://dilbert.com/strips/comic/2001-10-25/
Coincidence?
I don't think so.
And random.org agrees : http://www.random.org/analysis/
The problem is that you are creating a new Random instance with the same seed number each time. You should create a single Random instance (store it in a static if necessary) and simply call the next method on that same instance.
Random number generation is not truly random, see this Wikipedia entry for more details.
Salam to All,
Well it drove me crazy as well. The answer is simple. Change the seed before you generate random.
Example:
I want to generate random number between 1 to 10
Random rnd = new Random(DateTime.Now.Second);
int random_number = rnd.Next(10);
Put it inside a loop and run it three times. It will give out random numbers below 10.
Pseudo-random number generator usually work by choosing a seed, and then generating a deterministic sequence based on that seed. Choosing the same seed every time, you generate the same sequence.
There are "only" 2^32 different random sequences in .NET.
Not sure how the internals work.. check wiki for it, but it's very simple.
public class MathCalculations
{
private Random rnd = new Random();
public Int32 getRandom(Int32 iMin, Int32 iMax)
{
return rnd.Next(iMin, iMax);
}
}
public class Main
{
MathCalculations mathCalculations = new MathCalculations();
for (int i = 0; i < 6; i++)
{
getRandom(0,1000);
}
}
will generate Number1, Number2, Number3, Number4, Number5, Number6 (1 seed, 1 sequence of many numbers, random*not really, but approx.*)
if you however do this:
public class MathCalculations
{
public Int32 getRandom(Int32 iMin, Int32 iMax)
{
Random rnd = new Random();
return rnd.Next(iMin, iMax);
}
}
public class Main
{
MathCalculations mathCalculations = new MathCalculations();
for (int i = 0; i < 6; i++)
{
getRandom(0,1000);
}
}
You will now get Number1, Number1, Number1, Number1, Number1, Number1 (1 seed, 6 equal sequences of many numbers, always pick the same starting number from each equal sequence).. At some point Number1 will be different, because the seed changes over time.. but you need to wait some time for this, nonetheless, you never pick number2 from the sequence.
The reason is, each time you generate a new sequence with the same seed, hence the sequence is the same over and over again, and each time your random generated will pick the first number in it's sequence, which, with the same seed, is of course always the same.
Not sure if this is technically correct by the underlying methods of the random generator, but that's how it behaves.
In the event that anyone is looking for a "quick and dirty" "solution" (and I use that term with caution) then this will suffice for most.
int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds);
Random rand = new Random(secondsSinceMidnight);
var usuallyRandomId = rand.Next();
Please note my use of usually random. I agree that the item marked as the answer is a more correct way of doing this.
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
// Create a string array that consists of ten lines.
string[] personalNumbers; // declare personalNumbers as a 10-element array
personalNumbers = new string[10]; //= { "First number", "Second number", "Third line", etc}
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
Random random = new Random();
int randomNumber = random.Next(1, 50);
string RandomNumberText = Convert.ToString(randomNumber);
personalNumbers[i] = RandomNumberText;
}
Hi, I know that this SEEMS to be a duplicate of previously asked questions, but I am trying to
generate a series of random numbers between 1 and 50 to populate an array
The problem is, if I do it as we were taught in class, each number is the same
I know that the problem is that the tight loop causes the random to be seeded with the same number
What NONE of the other threads addresses however, is HOW to fix this problem when using a loop iteration....
All of the explanations thus far are so far advanced beyond our level that I (and the other askers BTW) have no clue how to implement them as a solution, which I also cannot submit in class as they are techniques that we have not covered
The tutorials at Microsoft insist that putting the random inside the loop is the right solution
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
Is there a straightforward way to use random to create a series of random numbers that doesn't run into this problem?
Create the random instance outside of the loop:
Random random = new Random();
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
MSDN:
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated. One
way to produce different sequences is to make the seed value
time-dependent, thereby producing a different series with each new
instance of Random. By default, the parameterless constructor of the
Random class uses the system clock to generate its seed value, while
its parameterized constructor can take an Int32 value based on the
number of ticks in the current time. However, 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.
You have to define the Random object outside the loop and just get a number each time inside the loop. If you create it each time again, it will be created with the same initial value because the interval between creations is too small.
Random random = new Random();
for (int i = 0; i < 9; i++) {
int randomNumber = random.Next(1, 50);
}
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.
thank you for the input, it is much appreciated!
I have posted the complete code thus far, which is now giving me what seems like "random" numbers
in that they are always different when I run it
#Steve thank you...I have looked at those questions, but all of the solutions involve using some other technique than random() which I am not allowed to use
#Oerkelens thank you, when I moved the code for random() outside the loop, I got two possible results
one was a series of 9, 9-digit random numbers, or an exception that says
Error 1 A local variable named 'randomNumber' cannot be declared in this scope because
it would give a different meaning to'randomNumber', which is already used in a 'parent or current' scope to denote something else
I have posted the larger bit of code to show what I have changed to get it to work...I don't really understand how to properly call the random() from within the loop, but for some reason, having the same line both inside and outside of the loop did the trick
#Preston - we don't have a textbook for this course, and we are only allowed to use techniques that are contained within the Microsoft C# video tutorials by Bob Tabor (learnvisualstudiodotnet) and Envato (learn C# in 30 days)
I apologize if this all seems obvious to you, but we are in the position of being told that half-way through the course that we are switching from learning to program in Visual Basic to C#, so all of our work now needs to be re-written in C#, without any particular instruction in how to how to use this language...needless to say, it is a huge stress and we are being left without any resources to do this, so much of what we are doing is guesswork
the more complete code that is "working"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace GuessingGameProgram
{
class Program
{
int randNum;
static void Main(string[] args)
{
// Create a string array that consists of ten lines.
string[] personalNumbers; // declare personalNumbers as a 10-element array
personalNumbers = new string[10]; //= { "First number", "Second number", "Third line", etc}
Random outsideLoopRandom = new Random();
int randomNumber = outsideLoopRandom.Next(1, 50);
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
randomNumber = outsideLoopRandom.Next(1, 50);
string RandomNumberText = Convert.ToString(randomNumber);
personalNumbers[i] = RandomNumberText;
}
// WriteAllLines creates a file, writes a collection of strings to the file,
// and then closes the file.
//System.IO.File.WriteAllLines(#"C:\Users\Public\TestFolder\WriteLines.txt", lines);
foreach (string i in personalNumbers) // this is just a test to see what the output is
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
}
}
//randNum = Random.Equals(1, 50);
//StreamReader myReader = new StreamReader("personalNumbers.txt");
//string line = "";
//while (line != null)
//{
// line = myReader.ReadLine();
// if (line != null)
// Console.WriteLine(line);
//}
//myReader.Close();
//Console.ReadLine();
//personalNumbers = RandomNumbers.next(1, 10);
//int returnValue = personalNumbers.Next(1, 50);
//int Guess = 0;
//Console.WriteLine("Please guess a number between 1 and 50");
//Console.ReadLine();
////while (Guess = Convert.ToInt32(Console.Read());
//if (Guess < returnValue)
//{
// Console.WriteLine("Wrong! the number that I am thinking of is higher than " + Guess + ". Try again!");
// Console.ReadLine();
//}
//if (Guess > returnValue)
//{
// Console.WriteLine("Wrong! The number that I am thinking of is lower than " + Guess + ". Try again!");
// Console.ReadLine();
//}
// else if (Guess = returnValue)
// Console.WriteLine("Correct! The number that I was thinking of was " + Guess + ". Congratulations!");
// //{
//Console.WriteLine("Let's play a guessing game!")
//Console.WriteLine("")
//Console.WriteLine("guess a number between 1 and 10")
//Console.WriteLine("")
//randNum = randomGenerator.Next(1, 10)
//While userGuess <> randNum
// {
// userGuess = Console.ReadLine()
// }
// If userGuess > randNum Then
// Console.WriteLine("too high, guess again!")
// {
// If userGuess < randNum Then
// Console.WriteLine("too low, guess again!")
// }
// Else
//End While
//Console.WriteLine("Correct! the secret number is " & randNum)
//Console.ReadLine()
My program needs to:
a. Generate an array of 20 random integers from zero to nine. Search for the first occurrence, if any, of the number 7, and report its position in the array.
b. Repeat the computation of part a 1000 times, and for each position in the array, report the number of times that the first occurrence of a 7 in the array is at that position
However whenever I run the program I get strange results (different every time) such as:
No sevens found at any position
1000 sevens found at one position and no sevens found anywhere else
Hundreds of sevens found in 2 positions, and none found anywhere else.
Does anyone have an idea what is wrong with my program?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Week_6_Project_2
{
class Program
{
static int intArrayLength = 20;
static int[] resultsArray = new int[intArrayLength];
public static Array generateRandomArray() {
int[] randomNumberArray = new int[intArrayLength];
Random random = new Random();
int popcounter = 0;
while (popcounter < intArrayLength) {
randomNumberArray[popcounter] = random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void searchForSevens()
{
int counter = 0;
int[] randomArray = (int[])generateRandomArray();
while (counter < intArrayLength)
{
if (randomArray[counter] == 7)
{
resultsArray[counter] += 1;
counter = intArrayLength;
}
counter += 1;
}
}
static void Main()
{
int searchCounter = 0;
while (searchCounter < 1000)
{
searchForSevens();
searchCounter += 1;
}
int displayCounter = 0;
while (displayCounter < intArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, resultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Your main problem is that each searchForSevens() test only takes a small fraction of time and the Random class uses auto-seeding from the clock. The clock however has a limited resolution. The result is that many (sometimes all) of your random sequences will be the same. And at most you will have 2 or 3 different result sets.
The simple fix for this single-threaded program is to use 1 static instance of Random.
You're instantiating a new instance of Random every time you call the generateRandomArray method. Since the random number generator uses the current time as a seed, instantiating two Random instances at the same time results in the same numbers being generated, which explains your unexpected results.
To solve your problem, you should only instantiate one Random instance, store it in private field, and reuse it every time you call the Next method.
The problem I assume stems from the fact, that Random() uses current time as seed. And the computation happens so fast, that each time new Random() is called, it uses same time. So you get same sequence of numbers.
To fix this, you simply need to set seed by yourself, incremmenting it every cycle should be enough.
long base = DateTime.Now.TotalMilliseconds;
Random rand = new Random(base+searchCounter);
.. something like that.
I will not answer but will try to give an analogy for the people that think that they need more then one Random instance...
Suppose that you need to fill 6 sheets of paper with random numbers from 1-6. Ask yourself this: do you need 6 dices or one to do the job? If you answer that you need more than one dice, ask yourself this: how different or more random is throwing different dice instead of same dice every time?
I mean, if you throw ONE on a dice, next throw of a dice won't have any less chance to be ONE again than it would be any other number. It goes against intuition, but it is mathematically and statistically so.
In your original code, you're calling the Random method in rapid succession [broken example based on OP's original code], thus seeding the method with the same number, resulting in duplicate "random" numbers. Creating a static member will ensure randomness simply because you're only creating a single instance of it.
Try creating a single static instance of random like this. [static member example].
static readonly Random Random = new Random();
Based on this, here's how I would solve your particular problem.
using System;
namespace Week_6_Project_2
{
class Program
{
// ******************************************
// THIS IS A SINGLE INSTANCE OF Random.
// read below as to why I'm seeding the instantiation of Random();
static readonly Random Random = new Random(Guid.NewGuid().GetHashCode());
// ******************************************
private const int IntArrayLength = 20;
static readonly int[] ResultsArray = new int[IntArrayLength];
public static Array GenerateRandomArray()
{
var randomNumberArray = new int[IntArrayLength];
var popcounter = 0;
while (popcounter < IntArrayLength)
{
randomNumberArray[popcounter] = Random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void SearchForSevens()
{
var counter = 0;
var randomArray = (int[])GenerateRandomArray();
while (counter < IntArrayLength)
{
if (randomArray[counter] == 7)
{
ResultsArray[counter] += 1;
counter = IntArrayLength;
}
counter += 1;
}
}
static void Main()
{
var searchCounter = 0;
while (searchCounter < 1000)
{
SearchForSevens();
searchCounter += 1;
}
var displayCounter = 0;
while (displayCounter < IntArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, ResultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Further reading about Random()
Beyond the answer above, sometimes it is necessary to seed Random(int); (I like to use the HashCode of a Guid) to ensure further randomness. This is because the default seed uses the clock which from the docs [microsoft] has a finite resolution. If your class is instantiated multiple times in quick succession (< 16ms), you will get the same seed from the clock... this breaks stuff.
[example of seeded Random(int) run in rapid succession with random results]
"using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers."
hear me when I say that you should NOT instantiate a new Random on every iteration of a loop -- use a static member
Another valid reason to implement your own seed is when you want to recreate a random sequence [example of two identical lists based on same seed]. Re-using the same seed will recreate the sequence since the sequence is based on the seed.
note: others might say that seeding it is not necessary [link], but I personally believe that for the additional few keystrokes and the microscopic hit on the clock, you might as well increase the probability of a unique seed. It doesn't hurt anything, and in some situations it can help.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Random number generator only generating one random number
I've distilled the behavior observed in a larger system into this code sequence:
for (int i = 0; i < 100; i++)
{
Random globalRand = new Random(0x3039 + i);
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
Running this from Visual Studio 2012 targeting .NET 4.5 will output either 316 or 315. Extending this beyond 100 iterations and you'll see the value slowly decrement (314, 313...) but it still isn't what I'd imagine anyone would consider "random".
EDIT
I am aware that there are several questions on StackOverflow already that ask why their random numbers aren't random. However, those questions have issues regarding one of a) not passing in a seed (or passing in the same seed) to their Random object instance or b) doing something like NextInt(0, 1) and not realizing that the second parameter is an exclusive bound. Neither of those issues are true for this question.
It's a pseudo random generator which basically creates a long (infinite) list of numbers. The list is deterministic but the order can in most practical scenarios be treated as random. The order is however determined by the seed.
The most random behaviour you can achieve (without fancy pants tricks that are hard to get right all the time) is to reuse the same object over and over.
If you change your code to the below you have a more random behaviour
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
The reason is the math behind pseudo random generators basically just creates an infinite list of numbers.
The distribution of these numbers are almost random but the order in which they come are not. Computers are deterministic and as such incapable of producing true random numbers (without aid) so to circumvent this math geniuses have produced functions capable of producing these lists of numbers, that have a lot of radnomness about them but where the seed is determining the order.
Given the same seed the function always produces the same order. Given two seeds close to each order (where close can be a property of which function is used) the list will be almost the same for the first several numbers in the list but will eventually be very different.
Using the first random number to generate the second. Doesnt make it any more "Random". As suggested try this.
Also as suggested no need to generate the random object inside the loop.
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
int value = globalRand.Next(1, 511);
Console.WriteLine(value);
}
I believe the Random() is time based so if your process is running really fast you will get the same answer if you keep creating new instances of your Random() in your loop. Try creatining the Random() outside of the loop and just use the .Next() to get your answer like:
Random rand = new Random();
for (int i = 0; i < 100; i++)
{
int value = rand.Next();
Console.WriteLine(value);
}
Without parameters Random c'tor takes the current date and time as the seed - and you can generally execute a fair amount of code before the internal timer works out that the current date and time has changed. Therefore you are using the same seed repeatedly - and getting the same results repeatedly.
Source : http://csharpindepth.com/Articles/Chapter12/Random.aspx