Hello there I want to generate random numbers, so I created method in my class
private readonly Random _rand = new Random(); //Private property of class
public void GenerateRandomNumber()
{
//For loop executes 10 times
for (int i = 1; i < 11; i++)
{
Console.WriteLine(_rand.Next(0, 10));
}
}
When I call this from Main I create new instance of my class and then call it. It works properly but I want to know why does this generate different numbers each time in for loop and also each time I run the program?
That's interesting for me because I know that Random can generate same numbers but in my case it generates different ones.
How will it affect if I add static modifier to private property?
In C# your random number generator will automatically set the seed to a value based on your system clock, thus generating pseudo random numbers. If you would like your random numbers to be in the same order every time you run the program you can manually set the seed using:
seed = 999
private readonly Random _rand = new Random(seed)
The Random object is not what's generating the numbers. When calling _rand.Next(0, 10), it's generating a random number between 0 and 9 which is why you are getting new numbers each time. See the documentation for Random.Next(). If you only want one random number, you will need to call this method outside of the loop and store the result in a variable.
Related
I am trying to access random elements from an array, but the Random generator that I am using keeps on giving me numbers in order like so:
The numbers will always come out sequenced, never completely random (ie. the next number is always greater until the max is reached, then starts from low numbers again). This can be incremental or decremental as well.
I am using a seeded Random object and Random.Next(-100, 100).
This is not the same as the behaviour demonstrated on the MSDN Random.Next page
All I can think of is that the version of .Net packaged with Unity does not have the most recent Random? Any solutions to this confusion?
//Example
//Seed and ods set before the Awake method is called
public int seed;
public GameObject[] pathPartOds;
Random random;
GameObject[] path;
void Awake ()
{
random = new Random (seed);
}
void CreatePath (int length)
{
path = new GameObject[length];
for (int i = 0; i < length; i++)
path[i] = pathPartOds[random.Next (0, pathPartOds.length)];
}
Have used multiple seeds and they all give the same result, and I have been creating seeds using a random int
You need to create an instance of Random exactly once and pass that as a parameter into your function that draws a random number.
Else you'll ruin the generator's statistical properties due to it being seeded in a systematic (i.e. non-random) way. That explains the piecewise monotonicity of your output.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Random number generator only generating one random number
I was a bit baffled with this few moments ago. I have the following code:
public blockType generateRandomBlock()
{
Random random = new Random();
int makeBlockOfType = random.Next(0, 100);
blockType t = blockType.normal;
if (makeBlockOfType <= 80 && makeBlockOfType >= 60)
{
t = blockType.blue;
}
else if (makeBlockOfType > 80 && makeBlockOfType <= 95)
{
t = blockType.orange;
}
else if (makeBlockOfType > 95 && makeBlockOfType <= 100)
{
t = blockType.green;
}
return t;
}
Fairly simple, it return an enum value based on a randomly generated number (based of system time). Unfortunately for some odd reason, I have all blocks either one color or the other even though this runs for every single block being put into the game. However, when I step through this with the debugger and then see the results after some run, I see that the blocks are now multi colored based on the chances provided. I am a little bit confused about why this is happening.
For this I am using MonoGame which uses the Mono compiler instead of the Microsoft one. Could this be the issue? I have tried to put this code inline into the constructor from where it is being called but I am getting the same result (I am guessing the compiler inlines the code anyways).
I have tried to restart Visual Studio it separately rather than letting the run do the build; no changes.
Any suggestions and help are greatly appreciated!
You should instanciate Random only once (set it as a private field and instanciate in the constructor), see the similar question : Random.Next returns always the same values
See the Random documentation :
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated
In your case, you create a Random instance with the same seed (too close in time) and you take the first value which will be the same for a given seed.
You are recreating your random number generator every time you call your method:
public blockType generateRandomBlock()
{
Random random = new Random();
As the seed of the random number generator is based on the time this will return the same value for consecutive calls.
Move your creation of the generator outside the routine:
Random random = new Random();
public blockType generateRandomBlock()
{
When you create multiple instances of Random successively in a very brief period of time, they are likely to end up getting initialized with the same time-dependent seed value.
To work around this, you should initialize your Random as an instance field instead:
private readonly Random random = new Random();
public blockType generateRandomBlock()
{
int makeBlockOfType = random.Next(0, 100);
// ...
}
The problem with the code is, when I try to generate a number, if the spin is equal 1 it generates values inside range (1,2,3) if if try to use the loop to sum random values inside the same range the random number gerated is always the same while in loop,
example, if I run the loop with:
spind3 = 4 the values go from 4, 8, 12
spind3 = 5 the values go from 5, 10, 15
That means the first time the RandomNumber generates a value inside loop, it never change until the loop completes.
if (toggled3.Checked)
{
if (spind3.Value != 1)
{
for (int i = 1; i <= spind3.Value; i++)
{
diceCalc[1] += RandomNumber(1, 4);
}
}
else
diceCalc[1] = RandomNumber(1, 4);
}
You are probably creating a new Random object inside RandomNumber method. The default constructor for Random uses the system time as a seed. If you create multiple Random objects in a tight loop the time probably won't have changed between each call so they will all be initialized with the same seed.
To fix your code you should only create one Random object and reuse it.
From the documentation:
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. For more information, see the Random(Int32) constructor.
The problem is that you are creating random generators too close in time. The random generator constructor uses the current time to seed the generator, and when you create them too close in time they will all be seeded using the same time.
Create one random generator and use in the loop:
Random rnd = new Random();
for (int i = 1; i <= spind3.Value; i++) {
diceCalc[1] += rnd.Next(1, 4);
}
You need to initialize your Random object, then call Next() inside your loop.
i.e.
if (toggled3.Checked)
{
// initialize your total and the random number generator
int diceTotal = 0;
Random rand = new Random();
for (int i = 0; i < spind3.Value; i++)
{
// add the next random number between 1 and 3
diceTotal += rand.Next(1, 4);
}
}
You can use Random(seed) constructor.
Random rand = new Random(Guid.NewGuid().GetHashCode());
One trick is to manually create the seed by adding DateTime.Now.Ticks to the variable i:
Random r = new Random((int)DateTime.Now.Ticks + i);
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
having an issue generating random numbers in a loop. Can get around it by using Thread.Sleep but after a more elegant solution.
for ...
Random r = new Random();
string += r.Next(4);
Will end up with 11111... 222... etc.
Suggestions?
Move the declaration of the random number generator out of the loop.
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, ...
Source
By having the declaration in the loop you are effectively calling the constructor with the same value over and over again - hence you are getting the same numbers out.
So your code should become:
Random r = new Random();
for ...
string += r.Next(4);
Random r = new Random();
for ...
string += r.Next(4);
new Random() will initialize the (pseudo-)random number generator with a seed based on the current date and time. Thus, two instances of Random created at the same date and time will yield the same sequence of numbers.
You created a new random number generator in each iteration and then took the first value of that sequence. Since the random number generators were the same, the first value of their sequences was the same. My solution will create one random number generator and then return the first, the second, etc... value of the sequence (which will be different).
I found a page in Chinese that said the same with the time: http://godleon.blogspot.hk/2007/12/c.html, it said if you type like this:
Random random = new Random(Guid.NewGuid().GetHashCode());
you MAY get a random number even in a loop! It solved my question as well!
You should be using the same Random instance throughout instead of creating a new one each time.
As you have it:
for ...
Random r = new Random();
string += r.Next(4);
the seed value is the same for each (it defaults to the current timestamp) so the value returned is the same.
By reusing a single Random instance like so:
Random r = new Random()
for ...
string += r.Next(4);
Each time you call r.Next(4) the values are updated (basically a different seed for each call).
Move the Random r = new Random(); outside the loop and just call next inside the loop.
For a part of a program i need the following 2 methods.
The first method listed will generated a random number.
where the 2nd method will "call" this method to fill the array.
The array has a max. number of elements defefined on 100 (and all the random generated numbers should be between 1-100).
The problem is i never get random numbers generated. (either i get 100 x the same value, 3 random numbers divided over the 100 max. elements of the array, or the same value 100 times all over again).
The problem should be in the first method, but i cannot seem to figure out the problem.
Been staring at this for quite some time now...
The problem should be with the return, cause it DOES create random generated numbers. But how do i return the generated value every time? (the int method has to be called with the 3 parameters).
private int ValidNumber(int[] T, int X, int Range)
{
for (byte I = 0; I < T.Lenght; I++)
{
Random RndInt = new Random();
X = RndInt.Next(1, Range+1);
}
return X;
}/*ValidNumber*/
public void FillArray(int[] T, int Range)
{
for (byte I = 0; I < T.Length; I++)
{
T[I] = ValidNumber(T, I, Range);
}
}/*FillArray*/
Console code:
public void ExecuteProgram()
{
ClsBereken Ber = new ClsBereken();
//const byte Range = 100;
const int Max = 100;
int[] T = new int[Max];
Ber.FillArray(T, Max);
DisplayArray(T);
}/*ExecuteProgram*/
private void DisplayArray(int[] T)
{
for (byte i = 0; i < T.Length; i++)
{
Console.Write("{0,4} ", T[i]);
}
Console.WriteLine();
}/*DisplayArray*/
Any help alot appreciated.
Kind Regards.
Re-use the Random instance. NOTE I've edited this to show passing the Random instance down, but I'm really not sure what ValidNumber is trying to do - it looks like it is juts burning up CPU cycles? I would suggest you can remove ValidNumber completely (and just use the next value from the Random in FillArray), but presumably you are trying to do something here - I'm just not sure what!
private int ValidNumber(int[] T, int X, int Range, Random random)
{
for (byte I = 0; I < T.Lenght; I++)
{
X = random.Next(1, Range+1);
}
return X;
}/*ValidNumber*/
public void FillArray(int[] T, int Range)
{
Random random = new Random();
for (byte I = 0; I < T.Length; I++)
{
T[I] = ValidNumber(T, I, Range, random);
}
}/*FillArray*/
When you create a Random, it is "seeded" using the system clock, but this is rounded heavily. If you create lots of Random in a tight loop, they all get the same "seed", so they all create the same next number.
If necessary you could move the Random further out (if you have other loops), or make it static (but if you do that you need to worry about synchronization too).
The problem is that you are reinitializing rndint over and over.
take the line:
Random RndInt = new Random();
and move it in front of the loop and see if that fixes it.
When you initialize a random object, it is assigned a seed (probably based on the time), and that seed is used to generate a series of seemingly random values. However, if you plug in the same seed to two random objects, you will get the same series of random numbers.
So, what is happening in your code is you are initializing a new random object with a seed, and then asking for the first random number in its series. Then, you are initializing another random object (even though it is assigned to the same name, it is a new object) and it is getting the same seed, and you are again asking for the first random number in the series. So naturally, you are getting the same random number over and over.
You are continuously creating an new Random object. I'm afraid this is seeded (randomized) by the timestamp of creation. Since this is really fast and happens multiple times, the seed is the same, and so is the result of the call RndInt.Next(1, Range+1);.
By the way, even though not incorrect, it's not a common practice in c#.net to start with a capital letter on names of local variables and parameters.
Any random number generation algorithm* is not truly random; it is simply a deterministic algorithm that has been specifically designed to output numbers that resemble randomness. (See Pseudorandom number generator.) Since the algorithm is deterministic, its output is completely dependent upon a starting "seed" value.
The Random class in .NET has two constructors: one which takes an integer seed, and another which takes no parameters. This one bases its seed off the current time.
From this information perhaps you can guess why creating a new Random instance for every value in your array results in the entire array being filled with the same number: every time you construct a Random object within a very small time frame, it will have the same seed value, which means it will generate identical output to another Random object constructed within the same time frame.
As Marc Gravell has already indicated, you should be using only a single Random instance to generate a sequence of random numbers.
*Well, almost any. I believe there are hardware implementations of random number generators that factor in random noise (taken from the surrounding environment) and may therefore be considered "truly" random. Whether you believe these are actually random
depends on your personal definition of "random" and whether or not you believe that we live in a deterministic universe.
You can pass Random() a seed but if you send it the same seed number you will get the same results. The way you are using it
Random rnd = new Random();
Is using an auto-generated seed based on time. But you may not get seemingly random results if you don't at least sleep for a second. (Source http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx)
As everyone has mentioned here already your biggest issue is the fact you keep recreating the random object each iteration.