This question already has an answer here:
-
How do I generate random integers within a specific range in Java?
65 answers
I'm currently working through an exercise where I am required to generate a random number which can be one of 4 values. (note I'm only allowed to use Math.random())
0
1
2
or 3
Currently I am using this: randno = (int) (Math.random()*4); // range 0-3
However, the outcome MUST have equal probability. My tests so far (although the method is lacking) shows that 3 occurs far less than the other numbers.
Is this coincidence? Or does my generator not have equal probability.
Thanks!
Your code works well:
public static void main(String[] args) {
int countZero = 0;
int countOne = 0;
int countTwo = 0;
int countThree = 0;
for(int i=0; i<400000; i++){
int randno = (int)(Math.random() * ((3) + 1));
if(randno == 0){
countZero++;
}
else if(randno == 1){
countOne++;
}
else if(randno == 2){
countTwo++;
}
else if(randno == 3){
countThree++;
}
}
System.out.println("Zero: " + countZero);
System.out.println("One: " + countOne);
System.out.println("Two: " + countTwo);
System.out.println("Three: " + countThree);
}
Output:
Zero: 99683
One: 99793
Two: 100386
Three: 100138
Just to make the comparison, I've put your approach next to this one.
public class Test {
private static int min = 0;
private static int max = 3;
private static Map<Integer, Integer> count = new HashMap<>();
public static void main(String[] args) {
OptionOne();
System.out.println("Option One: ");
for (Entry<Integer, Integer> entry : count.entrySet()) {
System.out.println(entry.getKey() + "\t " + entry.getValue());
}
count = new HashMap<Integer, Integer>();
OptionTwo();
System.out.println("\nOption Two:");
for (Entry<Integer, Integer> entry : count.entrySet()) {
System.out.println(entry.getKey() + "\t " + entry.getValue());
}
}
private static void OptionOne() {
for (int i = 0; i < 800000; i++) {
int number = min + (int) (Math.random() * ((max - min) + 1));
if (count.containsKey(number)) {
int sofar = count.get(number) + 1;
count.put(number, sofar);
} else {
count.put(number, 1);
}
}
}
private static void OptionTwo() {
for (int i = 0; i < 800000; i++) {
int number = (int) (Math.random() * 4);
if (count.containsKey(number)) {
int sofar = count.get(number) + 1;
count.put(number, sofar);
} else {
count.put(number, 1);
}
}
}
Output:
Option One:
0 199853
1 200118
2 200136
3 199893
Option Two:
0 199857
1 200214
2 199488
3 200441
Conclusion: your method works. Maybe your sample size wasn't enough?
With random numbers, you can random get what appears to be non random. There is no guarantee that all sequences appear random. http://vanillajava.blogspot.com/2011/10/randomly-no-so-random.html
For the right random seed you can appear to get a non-random sequence, but these are just as likely as any other.
Random random = new Random(441287210);
for (int i = 0; i < 10; i++)
System.out.print(random.nextInt(10)+" ");
}
prints
1 1 1 1 1 1 1 1 1 1
and
Random random = new Random(-6732303926L);
for(int i = 0; i < 10; i++)
System.out.println(random.nextInt(10)+" ");
}
prints
0 1 2 3 4 5 6 7 8 9
Lastly
public static void main(String ... args) {
System.out.println(randomString(-229985452)+' '+randomString(-147909649));
}
public static String randomString(int seed) {
Random rand = new Random(seed);
StringBuilder sb = new StringBuilder();
for (int i = 0; ; i++) {
int n = rand.nextInt(27);
if (n == 0) break;
sb.append((char) ('`' + n));
}
return sb.toString();
}
prints
hello world