How do you generate a random number with equal pro

2019-08-08 19:58发布

问题:

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!

回答1:

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


回答2:

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?



回答3:

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