C# code only gives expected results on step through? - c#

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);

Related

C# Best way to add abunch of sounds to a program and pick a random one to play?

I'm trying to get a voice line/Sound to play on form show however I only can play two different sounds and Id like to be able to have a list that gets played at random every time the form is shown, Anyone know the best way to go about this? here's the code I have right now:
if (Properties.Settings.Default.UI > 0)
{
var random = new Random();
SoundPlayer audio = new SoundPlayer(_2B.Properties.Resources.russian);
audio.Play();
}
else
{
SoundPlayer audio = new SoundPlayer(_2B.Properties.Resources.freedom);
audio.Play();
}
I tried adding a var for the random pick but it didnt work, I was assuming I could possibly do the same thing as this:
if (settings.version < newversionparsed)
{
bunifuCircleProgressbar1.Value +=1;
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[8];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
But im not too sure that it's working like I think, Nor do I know if this is possible.
Keep your Random so you would get a reasonable result
According to MSDN
On the .NET Framework, initializing two random number generators in a tight loop or in rapid succession creates two random number generators that can produce identical sequences of random numbers. In most cases, this is not the developer's intent and can lead to performance issues, because instantiating and initializing a random number generator is a relatively expensive process.
Both to improve performance and to avoid inadvertently creating separate random number generators that generate identical numeric sequences, we recommend that you create one Random object to generate many random numbers over time, instead of creating new Random objects to generate one random number.
So create one and use it multiple times is better.
Note: Random is not thread safe, but MSDN has an example for thread safe version.
Following is the example.
public static void Main()
{
Console.WriteLine("Hello World");
int len = 10;
int seed = 7;
string newEverytime = "";
for( int i =0 ; i < len; i++){
newEverytime+= new Random().Next( seed ).ToString();
}
Console.WriteLine( newEverytime ); // print something fixed
string get10Next="";
Random r = new Random();
for( int i =0 ; i < len; i++){
get10Next+=r.Next(seed);
}
Console.WriteLine( get10Next ); // print random string
}
For your program, you need to new a Random as a class member.
class Foo{
Random rnd = new Random();
void PlaySound(){
int val = rnd.Next( 1 ); // use a seed you like
// implement your play sound
}
}
Create an instance of Random somewhere, ideally static so you can easily reuse the same instance:
static Random random = new Random();
Create an array of all the sounds you want available to you:
string[] Stream = new Stream[] {
_2B.Properties.Resources.russian,
_2B.Properties.Resources.freedom
// Add as many sounds as you want
};
Then when you want to get a sound to play:
string sound = sounds[random.Next(sounds.Length)];
SoundPlayer audio = new SoundPlayer(sound);

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.

Why does Random.Next() always return the same number [duplicate]

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.

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));
}

Generating multiple random numbers

I want to generate 25 unique random numbers and list them in a console. The numbers should be atleast 10 characters long. Any easy way to do that?
Try building the numbers up as strings, and use a HashSet to ensure they are unique:
Random random = new Random();
HashSet<string> ids = new HashSet<string>();
while (ids.Count < 25)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; ++i)
{
sb.Append(random.Next(10));
}
ids.Add(sb.ToString());
}
Example output:
7895499338
2643703497
0126762624
8623017810
...etc...
The class HashSet is present in .NET 3.5 and newer.
The problem lies a little in "25 unique random". Displaying 25 random numbers is as easy as
Random r = new Random();
for(int i=0; i<25; i++)
Console.WriteLine(r.Next(1,100).ToString());
These are not necessarily unique, though. If you do not want to allow duplicates, you need to store previously generated numbers somehow, and roll again if you hit an old one.
Be aware that you change the probability distribution of your generated numbers this way.
Edit: I've just noticed that these numbers should be ten characters long. Since 9,999,999,999 exceeds Int32.MaxValue, I'd suggest using Math.Floor(r.NextDouble() * 10000000000 + 1000000000) instead of r.Next(1,100).
Since your numbers are that long, you should not need to worry about duplicates. They are very very unlikely.
There is a big different between Randomness and Uniqueness.
So if you need really unique numbers you have to make sure that you save somewhere all already created numbers and check if your newly created one isn't within this list or you have to provide some algorithm that ensures that a given number can't created twice.
To get the second part to work you mostly take the date/time of the creation moment, cause the current date/time pair is unique forever. The only problem is how many creations per (milli)second do you have and how many digits are available to store your unique number.
A sample about using 12 digits is made here. Hope this helps.
One simple way is this:
class Test
{
private static void Main()
{
Random rand = new Random();
for (int i = 0; i < 25; ++i)
{
Console.WriteLine(rand.Next(1000000000, int.MaxValue));
}
}
}
This will ensure that the numbers are always 10 characters (digits) long. They will not necessarily be unique however. If you want them to definitely be unique, you'll have to do something like this:
class Test
{
private static void Main()
{
Random rand = new Random();
var generatedSoFar = new HashSet<int>();
for (int i = 0; i < 25; ++i)
{
int newRand;
do
{
newRand = rand.Next(1000000000, int.MaxValue);
} while (generatedSoFar.Contains(newRand)); // generate a new random number until we get to one we haven't generated before
generatedSoFar.Add(newRand);
Console.WriteLine(newRand);
}
}
}
If you want to be able to have more than ten digits, you generate the number of digits randomly between 10 and your max number of digits. Then generate each digit (or group of digits) randomly in a StringBuilder or List. You can use the same HashSet method I used above to ensure uniqueness.
Random rnd = new Random(table);
for(int i = 0; i < 25; ++i) {
Console.WriteLine("{0}", rnd.Next(50, 50+i)
}

Categories

Resources