Reputation: 29
Random r1 = new Random();
for(int i=0; i<10; i++){
System.out.print(r1.nextInt(10) + " ");
}
output for one run: 9 7 6 8 3 5 3 3 0 4
why isn't 0-9 generated with equal probability? 3 alone occurs three times, but 1 & 2 zero times.
Upvotes: 2
Views: 1782
Reputation: 61158
From, the OP's comment the requirement becomes more clear:
I want to split a file with multiple lines. The split ratio is for instance 4:5. For 100 lines, 40 goes to one file and 50 to another file. And the split must be random
So random numbers are not required, what is required is a random order of numbers 1
to numLines
.
This will fulfil the requirement:
public List<Integer> randomLines(final int numLines) {
final List<Integer> lineNumbers = new ArrayList<>(100);
//put the line numbers into the List
//each line occurs exactly once
for (int i = 1; i <= numLines; ++i) {
lineNumbers.add(i);
}
final Random random = new Random();
//Carry out a random reording of the List
Collections.shuffle(lineNumbers, random);
return lineNumbers;
}
In order to test this code I created a simple test case:
Set<Integer.
for the line numbers of each fileSet
s have size splitPoint
and numLines - splitPoint
This works because a Set
can only contain unique items so if there were duplicates then the Set
s would have the wrong size:
@Test
public void testRandomLines() {
final App app = new App();
final List<Integer> lineNumbers = app.randomLines(100);
//pick a random split point
final int splitPoint = random.nextInt(lineNumbers.size());
System.out.println(splitPoint);
final Set<Integer> firstFile = new LinkedHashSet<>();
final Set<Integer> secondFile = new LinkedHashSet<>();
for (int i = 0; i < lineNumbers.size(); ++i) {
if (i < splitPoint) {
firstFile.add(lineNumbers.get(i));
} else {
secondFile.add(lineNumbers.get(i));
}
}
assertThat(firstFile.size(), is(splitPoint));
assertThat(secondFile.size(), is(lineNumbers.size() - splitPoint));
}
I hope this answers your question.
Upvotes: 0
Reputation: 649
If you want to randomize the order of the elements (0-9), you are likely looking for something like a Fisher-Yates Shuffle.
For example:
Random random = new Random();
int[] values = {1, 2, 3, 4, 5};
for(int i = values.length; i > 0; i--) {
int index = random.nextInt(i);
int i1 = values[index];
int i2 = values[i - 1];
values[i - 1] = i1;
values[index] = i2;
}
Upvotes: 2
Reputation: 691775
It seems you don't want random numbers, but a shuffled list of numbers (like a deck of 52 cards).
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
Collections.shuffle(list);
// now display them. They will appear in random order, each exactly once
for (Integer i : list) {
System.out.println(i);
}
Upvotes: 0
Reputation: 41281
Empirical probability is not the same as theoretical probability. What you see is the fact that in this case you got 3 3's and no 2's. If you were to run this again, you would get a different set. You would approach the theoretical probability as the number of runs increases.
As others mention, is tossing a coin twice and getting heads both times a sign that the coin is flawed or has an absurd probability of heads? No. If you tossed it a few million times and got all heads? That's a bit more likely then.
Upvotes: 5