C# Random of cordinates is linear - c#

My code is to generate random cordinates of lat and long within a bound:
Random lastLat = new Random();
Random lastLon = new Random();
for (int i = 0; i < 50; i++)
{
int lat = lastLat.Next(516400146, 630304598); //18.51640014679267 - 18.630304598192915
int lon = lastLon.Next(224464416, 341194152); //-72.34119415283203 - -72.2244644165039
SamplePostData d0 = new SamplePostData();
d0.Location = new Location(Convert.ToDouble("18." + lat), Convert.ToDouble("-72." + lon));
AddPushpin(d0);
}
My output looks like this:
http://img263.imageshack.us/img263/7504/capturerkv.png http://img263.imageshack.us/img263/7504/capturerkv.png
Is there something wrong with how my numbers are generated?

Jørn's answer gave the problem, but not the solution: just use a single instance of Random:
Random rng = new Random();
for (int i = 0; i < 50; i++)
{
int lat = rng.Next(516400146, 630304598);
int lon = rng.Next(224464416, 341194152);
SamplePostData d0 = new SamplePostData();
d0.Location = new Location(18d + lat / 1000000000d,
-72d - lon / 1000000000d);
AddPushpin(d0);
}
(I've changed the way of using the result, too - there's no need to convert to and from a string to achieve what you want. An alternative would be to call Random.NextDouble instead and multiply it by the size of the desired range, then add a base value.)
If you're calling routine multiple times, you should probably use a single instance of Random across those multiple calls. Beware though: Random in .NET is not thread-safe. Ideally you should have a single instance per thread. See my article on randomness for more details of how to handle Random.

You are initializing both of your Random instances without an explicit seed, causing them to return the same stream of pseudo-random numbers. What you are doing now, is equivalent of using DateTime.Now as the seed for both instances. As modern computers tend to execute code really fast, you end up with the same seed in both instances.
If you use a single Random instance for generating both lang and long you should see a much more "random" distribution.

You shouldn't use two different Random objects. Draw both latitude and longitude from the same Random.
Random random = new Random();
for (int i = 0; i < 50; i++)
{
int lat = random.Next(516400146, 630304598); //18.51640014679267 - 18.630304598192915
int lon = random.Next(224464416, 341194152); //-72.34119415283203 - -72.2244644165039
SamplePostData d0 = new SamplePostData();
d0.Location = new Location(Convert.ToDouble("18." + lat), Convert.ToDouble("-72." + lon));
AddPushpin(d0);
}

Your problem is you are creating two Random objects at the same time causing them to be seeded with almost the same Time seed.
Use just ONE object.

Related

Random Values for an Array?

I'm looking for some help with my array. to put it in context im trying to create a console application that randomly generates a 4-digit code for the user to guess.
to do this I need an array of [3] and they need to have random numbers assigned to it.
int[] secretCode = new int[3];
secretCode[0] =
secretCode[1] =
secretCode[2] =
secretCode[3] =
My concern is what would i put here to make them generate random numbers?
thank you for your help in advance.
You can use Linq and the Random class
Random rnd = new Random();
int[] secretCode =
Enumerable.Repeat(0, 4).Select(i => rnd.Next(1000, 10000)).ToArray();
or more traditionally
int SIZE = 4;
Random rnd = new Random();
int[] secretCode = new int[SIZE];
for (int i = 0; i < SIZE; i++)
{
secretCode[i] = rnd.Next(1000, 10000);
}
Note that there is a possibility of creating the same code more than once. The solution assumes you want something in the range 1000..9999 (10000 is an exclusive upper bound) since the code is to be 4 digits. If you would also allow smaller numbers, just adjust the Select portion.
As a side note, do not create a new instance of Random inside the select, as it would likely be reseeded to the same seed, based on the system time, resulting in the same "random" number over and over. Also Random is fast, but not cryptographically strong. If you need cryptographically valid randomness use RNGCryptoServiceProvider in place of Random.

What is the C# equivalent of this VB6 Rnd() call?

I am having a problem with the VB code Int(Rnd() * 75) + 75) conveting it to C#.
I have tried
Random random = new Random
random.Next( 75 ) + 75
But its isnt right. Please Help me.
Thanks
Assuming that's meant to give a value between 75 (inclusive) and 150 (exclusive) I'd use
Random random = new Random();
int value = random.Next(75, 150);
That's clearer than first generating a number in the range [0, 75) and then adding 75, IMO.
Note, however, that you shouldn't be creating a new instance of Random every time you want a random number. You probably want one instance per thread. I have a reasonably long article explaining the various pitfalls in generating random numbers, and some workarounds.
See your code in VB is doing
Generate a random number.
Multiply it with 75 and convert it into int.
Then add 75 in it.
In C# its like
Random random = new Random();
int v = random.Next() * 75 + 75;
No conversion required because random.Next() gives an integer. More over you can limit your random number generation by providing min and max value b/w which to find out like this:
random.Next(50, 100);
where it will only find random number b/w 50 and 100.
I think it like this
Random random = new Random();
int rdnum = (random.Next() + 1) * 75;
EDIT
At last if i need his random i will use this (0-20 for smaller numbers)
int rdnum = ((new Random()).Next(0, 20) + 1) * 75;
EDIT2
After comment of Deanna, code will be
Random random = new Random();
Double rdnum = (random.NextDouble() * 75) + 75;
Keep in mind that if you want exact Rnd function you can follow these steps:
1.In Solution Explorer, right click on references and click "Add Reference..."
2.In Assemblies -> Framework, check the checkbox of "Microsoft.VisualBasic"
Now you can use it like this:
Microsoft.VisualBasic.VBMath.Rnd();
Microsoft.VisualBasic.VBMath.Randomize();
Take note that Random Rnd = new Random(); should move out of for...loop in some cases:
Random Rnd = new Random();
float fRnd = (float)Rnd.NextDouble() * 75f + 75f;

XNA Randomly chosen Texture always picks same texture

I made this code to load about 8 different textures to a list of objects with a texture property.
I have a folder with textures named "1.png, 2.png, 3.png,.......,46.png" and I want the 8 different objects to be loaded with randomly chosen textures.
DockedFruitsList = new List<Fruit>(8);
for (int i = 0; i < 8; i++)
{
Fruit temp = new Fruit();
temp = new Fruit();
temp.Position = AvailablePositions[i];
int random=(new Random().Next(0, 4600) % 46);
temp.Texture = Content.Load<Texture2D>(#"Fruits/" + random);
DockedFruitsList.Add(temp);
}
The thing is, despite the random always generates a different number, the result of draw is always the same texture, it changes from a run to another run, but it's always the same for all the 8 textures
spriteBatch.Begin();
for (int i = 0; i < DockedFruitsList.Count; i++)
{
spriteBatch.Draw(DockedFruitsList[i].Texture, DockedFruitsList[i].Position, Color.White);
}
spriteBatch.End();
Try this out:
for (int i = 0; i < 100; i++)
Console.WriteLine(new Random().Next(0, 10));
Odds are you'll get an output like this:
5
5
5
.
.
.
This is because the seed of the Random class is initialized with a time-based value. If you initialize many instances of the Random class near the same point in time, then they will all end up with the same seed, and so the values they will produce will all be the same.
What you really want to do is to create one Random instance and use that for all your random values. The values generated will have no relation to each other:
var r = new Random();
for (int i = 0; i < 100; i++)
Console.WriteLine(r.Next(0, 10));
Output:
2
8
0
.
.
.
From the msdn:
The random number generation starts from a seed value.
If the same seed is used repeatedly, the same series of numbers is generated.
By default, the parameterless constructor of the Random class uses the system clock to generate its seed value
System clock it uses only changes its value every few milliseconds, so if you call new Random() very quickly it'll get seeded with the same number, thus the calls to Next... will yield identical results.
Note that if you debugged it, stepping through the code gave the system clock time to advance, thus you won't get the error unless it runs through the loop without you breaking / stepping through.
Create the Random object once, and reuse it (note i'm now converting random to string and i've called a different method on random too):
var rand = new Random();
DockedFruitsList = new List<Fruit>(8);
for (int i = 0; i < 8; i++)
{
Fruit temp = new Fruit();
temp = new Fruit();
temp.Position = AvailablePositions[i];
int random=(rand.Next(46) + 1);
temp.Texture = Content.Load<Texture2D>(#"Fruits/" + random.ToString());
DockedFruitsList.Add(temp);
}
new Random().Next(0, 4600)
means you initialize the rng every time (maybe with the same seed?)
Move the new outside the method (static member or similar).
Random is seeded by the time(GetTickCount()), the time changes only every few milliseconds. So all instances of random created within that interval will return the same sequence. The correct thing is only creating a single instance of Random outside the loop.
DockedFruitsList = new List<Fruit>(8);
Random rand = new Random();
for (int i = 0; i < 8; i++)
{
Fruit temp = new Fruit();
temp = new Fruit();
temp.Position = AvailablePositions[i];
int random=(rand.Next(1, 46));
temp.Texture = Content.Load<Texture2D>(#"Fruits/" + random);
DockedFruitsList.Add(temp);
}
Check Revisiting randomness for more details.
There is also no reason to use rand.Next(0, 4600)%46. You can use rand.Next(0,46) directly.
Note that this code will still return duplicate entries. If you want to avoid that entirely you can use:
Random rand=new Random();
foreach(int randomFruid in Range(1,46).Shuffle(rand).Take(8))
{
...
}
With Shuffle from Is using Random and OrderBy a good shuffle algorithm?

more than 1 sequence of random numbers c#, linq

i was using this code to generate a random sequence of numbers:
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * (new Random()).Next());
everything was ok till i need more than one sequence, in this code i call the routine 10 times, and the results are my problem, all the sequence are equal.
int i = 0;
while (i<10)
{
Console.Write("{0}:",i);
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * (new Random()).Next());
sequence.ToList().ForEach(x=> Console.Write(x));
i++;
Console.WriteLine();
}
Can someone give me a hint of how actually generate different sequences? hopefully using LINQ
The problem is that you're creating a new instance of Random on each iteration. Each instance will be taking its initial seed from the current time, which changes relatively infrequently compared to how often your delegate is getting executed. You could create a single instance of Random and use it repeatedly. See my article on randomness for more details.
However, I would also suggest that you use a Fisher-Yates shuffle instead of OrderBy in order to shuffle the values (there are plenty of examples on Stack Overflow, such as this one)... although it looks like you're trying to bias the randomness somewhat. If you could give more details as to exactly what you're trying to do, we may be able to help more.
You are creating 10 instances of Random in quick succession, and pulling the first pseudo-random number from each of them. I'm not surprised they're all the same.
Try this:
Random r = new Random();
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * r.Next());
In my code I use this static method I wrote many years ago, and it still shows good randomization:
using System.Security.Cryptography;
...
public static int GenerateRandomInt(int from, int to)
{
byte[] salt = new byte[4];
RandomNumberGenerator rng = RandomNumberGenerator.Create();
rng.GetBytes(salt);
int num = 0;
for (int i = 0; i < 4; i++)
{
num += salt[i];
}
return num % (to + 1 - from) + from;
}
Can't explain this example in detail, I need to bring myself back in time to remember, but I don't care ;)

Seeding a pseudo-random number generator in C#

I need a seed for an instance of C#'s Random class, and I read that most people use the current time's ticks counter for this. But that is a 64-bit value and the seed needs to be a 32-bit value. Now I thought that the GetHashCode() method, which returns an int, should provide a reasonably distributed value for its object and this may be used to avoid using only the lower 32-bits of the tick count. However, I couldn't find anything about the GetHashCode() of the Int64 datatype.
So, I know that it will not matter much, but will the following work as good as I think (I can't trial-and-error randomness), or maybe it works the same as using (int)DateTime.Now.Ticks as the seed? Or maybe it even works worse? Who can shed some light on this.
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random r = new Random(seed);
Edit: Why I need a seed and don't just let the Random() constructor do the work? I need to send the seed to other clients which use the same seed for the same random sequence.
new Random() already uses the current time. It is equivalent to new Random(Environment.TickCount).
But this is an implementation detail and might change in future versions of .net
I'd recommend using new Random() and only provide a fixed seed if you want to get a reproducible sequence of pseudo random values.
Since you need a known seed just use Environment.TickCount just like MS does. And then transmit it to the other program instances as seed.
If you create multiple instances of Random in a short interval (could be 16ms) they can be seeded to the same value, and thus create the same pseudo-random sequence. But that's most likely not a problem here. This common pitfall is caused by windows updating the current time(DateTime.Now/.UtcNow) and the TickCount(Environment.TickCount) only every few milliseconds. The exact interval depends on the version of windows and on what other programs are running. Typical intervals where they don't change are 16ms or 1ms.
If you need to seed it with something other than the current time (in which case you can use the default constructor), you can use this:
Random random = new Random(Guid.NewGuid().GetHashCode());
I had a similar question , to select a random set of questions from a larger list of questions. But when I use the time as the seed it gives the same random number .
So here is my solution.
int TOTALQ = 7;
int NOOFQ = 5;
int[] selectedQuestion = new int[TOTALQ];
int[] askQuestion = new int[NOOFQ];
/* Genarae a random number 1 to TOTALQ
* - if that number in selectedQuestion array is not o
* - Fill askQuestion array with that number
* - remove that number from selectedQuestion
* - if not re-do that - - while - array is not full.
*/
for (int i = 0; i < TOTALQ; i++) // fill the array
selectedQuestion[i] = 1;
int question = 0;
int seed = 1;
while (question < NOOFQ)
{
DateTime now1 = new DateTime();
now1 = DateTime.Now;
Random rand = new Random(seed+now1.Millisecond);
int RandomQuestion = rand.Next(1, TOTALQ);
Response.Write("<br/> seed " + seed + " Random number " + RandomQuestion );
if (selectedQuestion[RandomQuestion] != 0)
{
selectedQuestion[RandomQuestion] = 0; // set that q =0 so not to select
askQuestion[question] = selectedQuestion[RandomQuestion];
Response.Write(". Question no " + question + " will be question " + RandomQuestion + " from list " );
question++;
}
seed++;
}

Categories