简体   繁体   中英

Is Math.random() safe to use?

I have a method which is generating random integers. I don't want integers to be repeated, so I created this code -

int prevInt = 0;

private int randomInt() {
    int random = (int) (Math.random() * 3);
    //generate random numbers between 0 to 3 inclusive

    if(random == prevInt)
        return randomInt();
    //if previous random number is equal to currently generated
    //random number, then call this method again for a different
    //random number

    prevInt = random;
    return random;
    //else return the generated random number
}

Is the above code safe to use? At worst case scenario, can it be possible that all random integers generated by Math.random() * 3 are same?

private final Random random = new Random();

private int randomInt(final int prev, final int max) {
  final int next = random.nextInt(max - 1);
  if(next >= prev){
    return next + 1;
  }else{
    return next;
  }
}

This will return an int between 0 and max without the need to repeat.

public static double random()

Returns a double value with a positive sign , greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.

There are two principal means of generating random (really pseudo-random) numbers:

  1. the Random class generates random integers, doubles, longs and so on, in various ranges.

  2. the static method Math.random generates doubles between 0 (inclusive) and 1 (exclusive).

To generate random integers:

do not use Math.random (it produces doubles, not integers) use the Random class to generate random integers between 0 and N. To generate a series of random numbers as a unit, you need to use a single Random object - do not create a new Random object for each new random number.

Other alternatives are:

SecureRandom, a cryptographically strong subclass of Random
ThreadLocalRandom, intended for multi-threaded cases

please have a look at this post. SO Reference 1 , Reference 2

From the javadoc, Math.random() return a pseudo random and (approximately) uniform distributed number within the range.

So when you don't strict accuracy you may use it. Otherwise search for better solution.

try this trivial code and see for yourself

    for (int ran = 0; ran < 10; ran++) {
        int random = (int) (Math.random() * 3);
        System.out.println(random);
    }

Output in my case

2 2 0 2 1 0 0 0 2 1

是的,它很安全,但是我们永远不知道会发生什么,因此我们可以简单地将Math.random乘以两次以保持良好的安全性

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

First, I must point that your question title is not that clear. Safe can mean various thing. In this case I think you mean safety of algorithm of your code, not security nor only Math.random().

Unfortunately, your code is not algorithmically safe. Even if Math.random is safe, Your code has always positive possibility on running at any time: roughly speaking it means there are no guarantee that your code ends in finite time.

Assume you are taking random number among 4 numbers. If you are drawing random number excluding right before number, you're actually not drawing from 4 numbers: it's 3. I suggest another method:

int prevInt = -1;

private int randomInt() {
    if (prevInt == -1) {
        int random = (int) (Math.random() * 4);
        //generate random numbers between 0 to 3 inclusive
    } else if
        int random = (int) (Math.random() * 3);
        random = (random >= prevint) ? (random + 1) % 4 : random;
    }

    prevInt = random;
    return random;
}

private void resetRandom() {
    prevInt = -1;
    //use when you want to reset information that you have 'before' result.
}

This algorithm ends within finite time. Concern about whether Math.Random() itself is dangerous or whatever will be explained by other nice guys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM