1

I am trying to generate an array of random numbers. Each array entry will have a number between 0 and 31. I am trying to get the code to generate a random number and then check to see if that number exists in the array. If it does, it then generates a fresh random number and checks from the beginning again.

I thought I had it sussed with the code below:

 public class HelloWorld{
 public static void main(String []args){
 int[] randArray = new int[10];
 boolean firstNumber = true;
 int randNum = 0;
 for (int j=0; j < randArray.length; j++) {
 if(firstNumber) {
 randNum = (int)(Math.random() * 31 + 1);
 randArray[j] = randNum;
 firstNumber = false;
 } else {
 for (int k=0; k < randArray.length;) {
 randNum = (int)(Math.random() * 31 + 1);
 if(randArray[k] == randNum) {
 k=0;
 } else { 
 k++; 
 }
 }
 randArray[j] = randNum;
 System.out.println(j);
 }
 }
 System.out.println("-------");
 for(int i=0; i < randArray.length; i++) {
 System.out.println(randArray[i]);
 }
 }
}

But this is what it prints out:

1 2 3 4 5 6 7 8 9 ------- 25 17 19 20 24 4 26 30 6 24

As you can see, 24 is repeated twice. If I run the code again, you can see numbers being stored that are repeated.

Logically I cannot figure out why it is doing this. It may be something simple but I just can't see it.

I'm new to programming and this is something I thought I would test my knowledge with.

asked Mar 14, 2014 at 8:39
7
  • Could you elaborate on what you are trying to do? I think you are trying to shuffle all the numbers between 0 and 31 in an array. If so, there are better techniques. Commented Mar 14, 2014 at 8:42
  • Is there a reason why you're using an array instead of a Set or some other data structure? Commented Mar 14, 2014 at 8:42
  • Theoretically, a random number generator which always returns 42 is still random... If you want to ensure uniqueness of all numbers you'll have to check for yourself that a given number hasn't been generated yet. Commented Mar 14, 2014 at 8:42
  • I am trying to create an array of unique random numbers. so from 0 - 9 in the array will contain a unique random generated number. No duplicates. I am using an array because I am getting to grips with the basics and I haven't come across other data structures yet (they have only been breifly mentioned). Would an Array be limited for this task? Commented Mar 14, 2014 at 8:44
  • fge - this is what I am trying to accomplish with the 2nd for loop. I want it to check the array to make sure that it hasn't appeared yet in the array, if so, then to generate a new random number Commented Mar 14, 2014 at 8:45

7 Answers 7

2

Your approach to generating unique random numbers is wrong, because when you get to the last number n in your array, you only have a 1/n chance to generate that particular number you need. And because you are working with random numbers, it may happen that you may wait a long time before you successfully generate the entire array. Furthermore, the time to generate the array is wildly unpredictable.

A far better way to do it would be to generate an array with an increasing sequence, and shuffle this array. That way, you are guaranteed to generate the array in O(n), and shuffle the array in O(n).

int arraySize=32;
int[] myArray= new int(arraySize);
for(int i=0;i<arraySize;i++) {
 myArray[i]=i;
}
for(int i=0;i<arraySize;i++) {
 int randNum = (int)(Math.random() * (arraySize-1));
 int tmp=myArray[randNum];
 myArray[randNum]=myArray[i];
 myArray[i]=tmp;
}
answered Mar 14, 2014 at 8:45
Sign up to request clarification or add additional context in comments.

2 Comments

interesting - could you elaborate? I thought about setting up an array with no fixed length but as I understand you need to allocate a size to an array when you first create it
added code do show how it could be done. My java is a bit rusty, but hopefully you understand the solution.
1

You may try this code:

public static void main(String[] args) {
 Set<Integer> set = new HashSet<>();
 while (set.size() < 10) set.add((int)(Math.random() * 31) + 1);
 Integer[] randArray = set.toArray(new Integer[0]);
 for (int i = 0; i < randArray.length; i++) {
 System.out.print(randArray[i] + " ");
 }
 System.out.println();
}

EXAMPLE OUTPUT:

2 3 4 21 6 7 10 29 12 14
answered Mar 14, 2014 at 8:50

6 Comments

how would this check to see that the random number doesn't already exist in the array?
Set itself is a collection which cannot holds duplicate elements. tutorialspoint.com/java/java_set_interface.htm
This code does not explicitly check if an Integer is already in the set, because a Set contains only distinct elements. The while-loop tries to add Integers till the number of distinct Integers is 10. Hence, you do not have to do the check by yourself. The Set does it for you.
I assume that Sets would be beyond the scope of a beginner? So far I have only come across Arrays as data storage. Is this considered a more advanced topic?
+1 nice and clear, but does suffer from a deep copy to coerce into an array.
|
1

You are regenerating the random number each time you check on a row, rather than comparing the same number with all the array values in the inner loop.

Which you should be doing here is check the whole array against the same random number, and if you find a coincidence, set k to 0 and regenerate the random number to try again.

answered Mar 14, 2014 at 8:45

1 Comment

This is the correct answer, with regards to why you get duplicates. You create a new random number in the inner k=0; k < randArray.length loop. You check a new random number with one index in the randArray, instead of the same random number with each index. If you create the random number in the j=0; ... loop instead if should work. Also, you can get rid of the firstNumber stuff by just initialing randArray[0] to a new random number and loop from j=1; j < randArray.length.
1

I'd use a Fisher-Yates shuffle to do this. It's the fastest way I know, at the expense of a little excess memory consumption. But it doesn't suffer from any retry overhead.

/*pseudocode; populate `arr` to taste. I'd be tempted to write it long-hand*/
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ..., 31}; 
/*Implement Fisher-Yates shuffle in its own scope block*/
{
 Random random = new Random();
 for (int i = arr.length - 1; i > 0; i--){
 int r = random.nextInt(i + 1);
 /*exhange r and i*/
 int t = arr[r];
 arr[r] = arr[i];
 arr[i] = r;
 }
}
/*ToDo - either rescale `arr` or just use the first 10 elements*/
answered Mar 14, 2014 at 8:52

Comments

1

Another Solution. Mark numbers which was generated.

public static void main(String[] args) {
 int[] randArray = new int[10];
 int randNum = 0;
 boolean[] isPresented = new boolean[32];
 for (int i = 0; i < randArray.length; ) {
 randNum = (int)(Math.random() * 31 + 1);
 if(!isPresented[randNum]){
 randArray[i] = randNum ;
 isPresented[randNum] = true;
 i++;
 }
 }
 System.out.println(Arrays.toString(randArray));
}
answered Mar 14, 2014 at 8:57

Comments

0

In the second for loop, you are generating a random number for every iteration of the loop. Change the loop as shown below.

else {
 // generate a random number before the loop begins
 randNum = (int)(Math.random() * 31 + 1); 
 for (int k=0; k < randArray.length;) {
 if(randArray[k] == randNum) {
 k=0;
 // generate a random number only if the number exists in the array
 randNum = (int)(Math.random() * 31 + 1); 
 } else { 
 k++; 
 }
 }
 randArray[j] = randNum;
 System.out.println(j);
 }
answered Mar 14, 2014 at 8:51

Comments

0

As far as I know the easiest and most efficient way of generating a (not very large) set of unique random numbers is (it is somewhat similar to method suggested by Bathsheba):

1) generate an ArrayList of unique sequential numbers to cover all required range
2) access the ArrayList using random index and moving (get and remove from the array) the entry at the index.

This way after ArrayList.size() iterations you will have a resulting array of unique random numbers.

answered Mar 14, 2014 at 10:19

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.