Thahleel al-Aleem
Thahleel al-Aleem

Reputation: 781

Equal probability in Java

How can I get the Math.random() call to have absolute equal probability for 4 cases? (ie 0.25 for case 1, 0.25 for case 2, 0.25 for case 3, 0.25 for case 4)?

I currently get 0.05 for Case 1, 0.075 for Case 2, 0.45 for Case 3 and 0.425 for Case 4.

Been trying to work out why it does this for hours with not much success.

int direction = 0;

        // Select a random number

        randno = (int) Math.round(Math.random() * 3);

        // Convert this to a direction

        while (direction == 0) {
            if (randno == 0 && !isWall(robot, Robot.LEFT)) direction = Robot.LEFT;
            else if (randno == 1 && !isWall(robot, Robot.RIGHT)) direction = Robot.RIGHT;
            else if (randno == 2 && !isWall(robot, Robot.BEHIND)) direction = Robot.BEHIND;
            else if (!isWall(robot, Robot.AHEAD)) direction = Robot.AHEAD;
            else randno = (int) Math.round(Math.random() * 3);
        }

Upvotes: 1

Views: 1415

Answers (3)

Jonah
Jonah

Reputation: 1003

This might do the trick

Run to see the probability of each case

    int case1 = 0;
    int case2 = 0;
    int case3 = 0;
    int case4 = 0;

    for(int i = 0; i < 100; i++)
    {
        double probability = Math.random();

        if(probability < 0.25)
        {
            /* case 1 */
            case1++;
        }
        else if(probability < 0.5 && probability > 0.25)
        {
            /* case 2 */
            case2++;
        }
        else if(probability < 0.75 && probability > 0.5)
        {
            /* case 3 */
            case3++;
        }
        else
        {
            /* case 4 */
            case4++;
        }
    }

    System.out.println("Number of different cases");
    System.out.println("Case 1 = " + case1);
    System.out.println("Case 2 = " + case2);
    System.out.println("Case 3 = " + case3);
    System.out.println("Case 4 = " + case4);

Remove the for-loop and all the printing and you should be good to go

Upvotes: 0

zapl
zapl

Reputation: 63955

Math.random() * 3 results in values in the range [0, 3). appplying Math.round to that means:

  • [0, 0.5) becomes 0. - 0.5 out of 3 means 1/6th probability.
  • [0.5, 1.5) becomes 1 - twice as big as above range, 2/6th
  • [1.5, 2.5) becomes 2 - same as above, 2/6th
  • [2.5, 3) becomes 3. Just 1/6th again.

Next up, you also combine those unevenly distributed numbers with isWall. Especially cases like (randno == 0 && isWall(robot, Robot.LEFT)) (value is 0 but there is a wall) are also added to the last case.

What you really need is a) a method like

double probability = Math.random();
if (probability < 0.25) {
    ..

that doesn't have screwed up distribution.

b) don't let choices fall through. Even the last case in your code needs to limit by randno or it eats up cases that don't belong there.

Also you may have to rethink what you're measureing. As what do you count it when it decides to go left but there is a wall? Choices can be even but walls don't care. Perfect even distribution is only possible when there are no walls.

Upvotes: 3

antonpp
antonpp

Reputation: 2383

If you want yo use Math.random() you can try something like this:

    double probability = Math.random();

    if (probability < 0.25) {
        /* case 1 */
    } else if (probability < 0.5) {
        /* case 2 */
    } else if (probability < 0.75) {
        /* case 3 */
    } else {
        /* case 4 */
    }

Upvotes: 0

Related Questions