Click here to Skip to main content
15,867,756 members
Please Sign up or sign in to vote.
1.80/5 (2 votes)
See more:
I used the Random class "Next(int32, int32) method to generate a random number which falls withing the range.
Let's say the range is pretty large. The difference between param1 and param2 is 100.

If I need a random number in an iteration (assume 5 times), then 3 out of the 5 times I get the same value.

How to get the random number which does not repeat for the range?
Or should I just use the Random Number generators provided by Crypto Service?

What I have tried:

1. First solution involved creating new instance in a loop.
public List<string> GetRandomRecords(List<string> records, int requiredRecords)
        {
            var numberOfRecords = records.Count;

            var randomRecords = new List<string>();

            for (int i = 0; i < requiredRecords; i++)
            {
                var randomGenerator = new Random();

                while (true)
                {
                    var randomIndex = randomGenerator.Next(0, numberOfRecords);

                    var record = records[randomIndex];

                    if (!randomRecords.Contains(record))
                    {
                        randomRecords.Add(record);
                        break;
                    }
                }
            }

            return randomRecords.OrderBy(item => Guid.NewGuid()).ToList();
        }


2. Modified the solution to use the same instance in a loop.

public List<string> GetRandomRecords(List<string> records, int requiredRecords)
       {
           var numberOfRecords = records.Count;

           var randomRecords = new List<string>();

           var randomGenerator = new Random();

           for (int i = 0; i < requiredRecords; i++)
           {
               while (true)
               {
                   var randomIndex = randomGenerator.Next(0, numberOfRecords);

                   var record = records[randomIndex];

                   if (!randomRecords.Contains(record))
                   {
                       randomRecords.Add(record);
                       break;
                   }
               }
           }

           return randomRecords.OrderBy(item => Guid.NewGuid()).ToList();
       }
Posted
Updated 7-Dec-17 20:32pm
v2
Comments
Patrice T 7-Dec-17 23:38pm    
Show your code !
Dave Kreskowiak 7-Dec-17 23:50pm    
It sounds like you're creating a new instance of Random inside a loop. Don't do that! But, we can't tell because we can't see your code.
George Swan 8-Dec-17 2:18am    
One approach for generating unique random numbers within a given range is to place all the numbers in the required range into an array. Shuffle the array and take the required items consecutively from the array.

Suppose you have to extract 5 numbers in the 1..100 range. The odds of getting one or more duplicates are:
p=(100^5 - 100*99*98*97*96)/100^5 ≅ 9.7 %

So, in about ten percent of the cases you are going to get dulpicates (if you observe a greater frequency then either there is a bug in your code or (less probably) the random generator is incorrect.

To avoid duplicates without the time consuming check and reject approach, follow the algorithm I described here: Random extraction of 5 cards from a deck[^] (I know it's C++, but you can easily convert it to C#).
 
Share this answer
 
The nature of "Random numbers" is that they do not in any way guarantee uniqueness in a small set like yours: in fact they can never guarantee uniqueness regardless of the sample size - the next number has no relation to the previous ones except statistically.
And creating your random generator instance inside the loop doesn't help, because it is preset from the system clock, so it's very likely that multiple instances will start with the same value (given that Random is not truly random, it's pseudo random like all software based random number generators).

If you want to draw from a pool of unique numbers only, then set up an new List<int> and fill it with the range of values. Then use that to provide your unique string:
private Random randomGenerator = new Random();
public List<string> GetRandomRecords(List<string> records, int requiredRecords)
    {
    int numberOfRecords = records.Count;
    List<string> randomRecords = new List<string>();
    List<int> indexes = Enumerable.Range(0, requiredRecords).ToList();
    for (int i = 0; i < requiredRecords; i++)
        {
        int randomIndex = randomGenerator.Next(0, indexes.Count);
        int index = indexes[randomIndex];
        indexes.RemoveAt(randomIndex);
        string record = records[index];
        randomRecords.Add(record);
        }
    return randomRecords;
    }
}
 
Share this answer
 
Try this code. You should check each number that you generate against the previous numbers.
public List<string> GetRandomRecords(List<string> records, int requiredRecords)
{
	var numberOfRecords = records.Count;
	var randomRecords = new List<string>();
	var randomGenerator = new Random();
	int randomIndex;
	for (int i = 0; i < requiredRecords; i++)
	{
		do
		{
			randomIndex = randomGenerator.Next(0, numberOfRecords);
		} while(randomRecords.Contains(record));
		randomRecords.Add(randomIndex);
	}
	return randomRecords.OrderBy(item => Guid.NewGuid()).ToList();
}
 
Share this answer
 
Comments
nitin_ambupe 8-Dec-17 1:09am    
That I am already doing. A Record is considered as new only if it is not available in the list.
The problem is, Random generates the same number again and again and sometimes this gets stuck for a pretty long time. (Looks like a hang on UI Part).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900