0

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

mjsr
  • 7,410
  • 18
  • 57
  • 83
  • 1
    And if `OrderBy` does call the key selector more than once(I didn't find anything in the documentation on whether is guarantees only calling once) your code become faulty since then the comparer contract would be violated. – CodesInChaos Dec 04 '10 at 13:07

3 Answers3

5

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.

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • hi Jon, im creating individuals for a genetic algorithm. I test the goodnes of this sequence generator drawing the resulting points (using one point and the next has coordinates x ,y in a rectangle). The results was good, i don't see any pattern in the picture. I was reading about the seed value. If in the code i add "i" as seed, then all the sequence are different, is this fine?, the seed must have some extra property? – mjsr Dec 04 '10 at 13:15
  • @voodoomsr: It depends on whether you want it to be predictable - if you need unpredictability, you need an unpredictable seed too. If you pass in the same seed each time, you'll get the same results each time. – Jon Skeet Dec 04 '10 at 13:16
  • mmm if i create a seed that is actually other random number, i get different results, i think this could be enough unpredictable. I'm going to look further the Fisher-Yates algorithm. At first sight doesn't look difficult to implement – mjsr Dec 04 '10 at 13:59
  • @voodoomsr: If you look at the second link in the second paragraph, you'll see an existing implementation. – Jon Skeet Dec 04 '10 at 16:43
2

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());
tomfanning
  • 9,552
  • 4
  • 50
  • 78
0

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

Genius
  • 1,784
  • 14
  • 12
  • It's not going to be much use if you want a number greater than 1024 though, is it? And if you ask for (say) 1-700 you'll find it doesn't give a good distribution. Additionally, creating a new random number generator each time is not a good idea. It would be better to have a subclass of Random which delegated to an instance of RandomNumberGenerator if you really need cryptographically secure random numbers. Otherwise, just use Random. – Jon Skeet Dec 04 '10 at 16:45
  • To whom who voted -1: did you try this code? Separate joking-style answer and misunderstanding the question – Genius Dec 04 '10 at 16:47
  • @Jon Skeet, 1) it does a good distribution with modifying the code little bit (see the answer as an idea, not as an instruction). 2) Why creating randomnumbergen is not a good idea? performance? who cares in this question? 3) RandomNumberGenerator from cryptographic and Random from System are different classes with very different implementation – Genius Dec 04 '10 at 16:52
  • @Genius: I was the one who downvoted this code, because it's *bad code*. 1) It's got a *terrible* distribution for any even slightly large numbers. 2) Part of the *point* of RNG is that you can keep reusing the same instance. Why go against the idiom? 3) Yes, I know they're very different. But you can override appropriate methods in Random to put the convenient API of Random over the cryptographically secure randomness of RandomNumberGenerator. – Jon Skeet Dec 04 '10 at 17:39
  • @Jon Skeet, never used this method for large numbers. mb you're right - for large numbers this method will not be useful, but author said nothing about it. P.S.: I thought votedown is for answers that are quite incorrect, but not when just "I disagree with this point of view". – Genius Dec 04 '10 at 17:52
  • @Genius: They're for answers which are unhelpful. I consider this code to be unhelpful - it is *incredibly* limited, and even for relatively small numbers the distribution isn't uniform. – Jon Skeet Dec 04 '10 at 18:53
  • @Jon Skeet, dude, don't mess your opinion with other opinions, ok? This code works and helpful at least for me, and mb for someone else. If this is not for you - go ahead, don't stay in line. Peace! – Genius Dec 06 '10 at 08:38