I use this code:
ArrayList generatedNumbers = new ArrayList();
int MinLimit = 0;
int MaxLimit = 10;
Random R = new Random();
int randomNum;
numOfGenerated = 7;
for(int i=0;i<numOfGenerated;i++)
{
randomNum= R.Next(MinLimit,MaxLimit);
generatedNumbers.Add(randomNum);
}
Any idea how to solve the problem?If you generate seven random numbers between 0 and 10, it is very very likely that you will get duplicate numbers (easy to calculate, by the way).
If what you want is to extract the numbers only once and at random, you can use a little trick, which would be to mark the numbers you've already chosen.
Here's some code (not checked, but you should see the spirit):
ArrayList generatedNumbers = new ArrayList();int MinLimit = 0;
int MaxLimit = 10;
Random R = new Random();int randomNum;
numOfGenerated = 7;bool[] alreadyUsed = new bool[MaxLimit];
if (numOfGenerated > MaxLimit) {
throw new Exception("Can't extract that many numbers");
}for(int i=0;i<numOfGenerated;i++)
{
randomNum= R.Next(MinLimit,MaxLimit);
while (alreadyUsed[randomNum]) {
randomNum = (randomNum + 1) % MaxLimit;
}
generatedNumbers.Add(randomNum);
}
If finds the nearest available number after the randomly chosen position. I wouldn't guarantee this is purely random, though, as this probably introduces some artefacts...
"I wouldn't guarantee this is purely random, though, as this probably introduces some artefacts...
"
Yes, I always get same numbers :-)
I don't quite understand the logic behind Bertrand's script (it doesn't appear to turn any boolean value to true, which is how it would indicate that the number is already present and also adding 1 and then finding the modulus??), however I think the major flaw is your logic and not the random method. Keeping the range of possible random numbers the same, or very close to, the number of numbers that you want to store will always produce duplicates. For example:
If you have an array for two numbers and only allow the random numbers to be either 1 or 2, the result could be:
1,1
1,2
2,1
2,2
which means that there is a 50% probability that there will be duplicates.
Increasing the random number range to 10 and the array to 7 does, obviously, reduce that probability (slightly), however it is still highly likely that there will be duplicates.
To solve this you could either replace the for loop in Bertrand's script with:
for(int i=0;i<numOfGenerated;i++) {or increase the range of possible random numbersrandomNum = R.Next(MinLimit,MaxLimit);
if ( !alreadyUsed[randomNum] ) {generatedNumbers.Add(randomNum);
alreadyUsed[randomNum] = true;
}
}
I have allready added part
"alreadyUsed[randomNum] = true;" before I posted my previous comment.
If I put yoour code, Steven, I'll not get same number of random numbers for every load.
Bertrand's script works welll but it get's same number's in diferent combination.
I think it is a result of small number of posible combinations. This is my code:
Random R = new Random((int)System.DateTime.Now.Ticks);
int MinLimit = 0;
int MaxLimit = numOfGenerated;
bool[] alreadyUsed = new bool[MaxLimit];
for(int i=0;i<numOfGenerated;i++)
{
randomNum = R.Next(MinLimit,MaxLimit);
while (alreadyUsed[randomNum])
{
randomNum = (randomNum + 1) % MaxLimit;
}
alreadyUsed[randomNum] = true;
generatedQuestions.Add(randomNum);
}
You could use a Diffrent approach. If you generate a initial ArrayList with all the numbers and start picking random numbers from it and deleting it from the List
like
public int[] GetRandomNumbers( int minValue, int maxValue, int numCount )
{
int[] randomNumbers = new int[ numCount ];
ArrayList numbers = new ArrayList( maxValue - minValue );
Random rand = new Random();
int index;
for( int i = minValue; i < maxValue; i++ )
numbers.Add( i );for( int i = 0; i < numCount; i++ )
{
index = rand.Next( numbers.Count );
randomNumbers[ i ] = (int)numbers[ index ];
numbers.RemoveAt( index );
}return randomNumbers;
}
I had forgotten to set the booleans, but you had figured that out yourself. But do you get the expected results or are you still expecting something different?
As I said. I get expected result, but I get always same numbers with diferent positions combination. I suppose that is a result of small number of possible combinations.
Could be an artefact, too.
A really random algorithm would be to decrement the random interval, and always start from the zero position, like this (pseudo-code):
int max = 10;
int remainingIntegers = max;
bool[] alreadyChosen = new bool[max];
int nbIntegers = 7;
int[] randomNumbers = new int[nbIntegers];
Random rnd = new Random();
for (int i = 0; i < nbIntegers ; i++) {
int random = rnd(0, remainingIntegers);
int index = 0;
for (int j = 0; j < random ; j++) {
while (alreadyChosen[index]) {
index++;
Debug.Assert(index < max);
}
}
randomNumbers[i] = index;
alreadyChosen[index] = true;
}
(not tested)
0 comments:
Post a Comment