148

What is the difference between Math.random() * n and Random.nextInt(n) where n is an integer?

Gili
  • 86,244
  • 97
  • 390
  • 689
  • I don't know the math, but I know that FindBugs complains if you use `Math.random()` – finnw Feb 13 '10 at 00:56
  • 3
    Remember that Random has no static method, so use: (new Random()).nextInt(n)). For Math to generate a similar integer use: Math.floor((Math.random()*n)+1); – Dimitri Dewaele Jan 23 '14 at 15:28

4 Answers4

186

Here is the detailed explanation of why "Random.nextInt(n) is both more efficient and less biased than Math.random() * n" from the Sun forums post that Gili linked to:

Math.random() uses Random.nextDouble() internally.

Random.nextDouble() uses Random.next() twice to generate a double that has approximately uniformly distributed bits in its mantissa, so it is uniformly distributed in the range 0 to 1-(2^-53).

Random.nextInt(n) uses Random.next() less than twice on average- it uses it once, and if the value obtained is above the highest multiple of n below MAX_INT it tries again, otherwise is returns the value modulo n (this prevents the values above the highest multiple of n below MAX_INT skewing the distribution), so returning a value which is uniformly distributed in the range 0 to n-1.

Prior to scaling by 6, the output of Math.random() is one of 2^53 possible values drawn from a uniform distribution.

Scaling by 6 doesn't alter the number of possible values, and casting to an int then forces these values into one of six 'buckets' (0, 1, 2, 3, 4, 5), each bucket corresponding to ranges encompassing either 1501199875790165 or 1501199875790166 of the possible values (as 6 is not a disvisor of 2^53). This means that for a sufficient number of dice rolls (or a die with a sufficiently large number of sides), the die will show itself to be biased towards the larger buckets.

You will be waiting a very long time rolling dice for this effect to show up.

Math.random() also requires about twice the processing and is subject to synchronization.

user11153
  • 8,536
  • 5
  • 47
  • 50
matt b
  • 138,234
  • 66
  • 282
  • 345
  • 3
    Random.nextInt and nextDouble are also subject to synchronization. – adrianos Nov 18 '14 at 16:05
  • In this context, what does "less biased" mean, please? – ΦXocę 웃 Пepeúpa ツ Aug 16 '16 at 08:41
  • 2
    @ΦXocę웃Пepeúpaツ It simply means that certain numbers are more likely to be drawn than others. As in it is biased to picking some numbers over others (hence not totally random or given large enough sample size uniform) – ford prefect Oct 11 '16 at 14:56
  • 1
    Note that the last comment to that thread reports: "The bias that was described is one part in 2^53, but the maximum cycle length of the PRNG used is only 2^48. So what you will see in the application is the data distribution of the underlying PRNG, not the bias." This would point to the fact that the two methods are equivalent – digital illusion Jun 05 '17 at 10:06
  • 2
    @ΦXocę웃Пepeúpaツ Replace `6` with `5` on a dice cube: it will be "5-biased". You can throw the dice a couple of times before you notice that something is wrong with the dice. You are forced to perform an extremely sophisticated thorough examination before you notice that something is wrong with a random generator. – Dávid Horváth Oct 25 '18 at 10:20
28

another important point is that Random.nextInt(n) is repeatable since you can create two Random object with the same seed. This is not possible with Math.random().

dfa
  • 114,442
  • 31
  • 189
  • 228
15

According to https://forums.oracle.com/forums/thread.jspa?messageID=6594485&#6594485 Random.nextInt(n) is both more efficient and less biased than Math.random() * n

Gili
  • 86,244
  • 97
  • 390
  • 689
  • 23
    I would recommend actually quoting some of his post and summarizing a little here. The link should be supplemental to your answer. – jjnguy Apr 10 '09 at 19:34
  • the link is broken. – douyu Mar 02 '23 at 10:46
  • @douyu I regret not quoting the article inline. Fortunately https://stackoverflow.com/a/738651/14731 did so before the link went down. – Gili Mar 04 '23 at 02:07
0

According to this example Random.nextInt(n) has less predictable output then Math.random() * n. According to [sorted array faster than an unsorted array][1] I think we can say Random.nextInt(n) is hard to predict.

usingRandomClass : time:328 milesecond.

usingMathsRandom : time:187 milesecond.

package javaFuction;
import java.util.Random;
public class RandomFuction 
{
    static int array[] = new int[9999];
    static long sum = 0;
    public static void usingMathsRandom() {
        for (int i = 0; i < 9999; i++) {
         array[i] = (int) (Math.random() * 256);
       }

        for (int i = 0; i < 9999; i++) {
            for (int j = 0; j < 9999; j++) {
                if (array[j] >= 128) {
                    sum += array[j];
                }
            }
        }
    }

    public static void usingRandomClass() {
        Random random = new Random();
        for (int i = 0; i < 9999; i++) {
            array[i] = random.nextInt(256);
        }

        for (int i = 0; i < 9999; i++) {
            for (int j = 0; j < 9999; j++) {
                if (array[j] >= 128) {
                    sum += array[j];
                }
            }

        }

    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        usingRandomClass();
        long end = System.currentTimeMillis();
        System.out.println("usingRandomClass " + (end - start));
        start = System.currentTimeMillis();
        usingMathsRandom();
        end = System.currentTimeMillis();
        System.out.println("usingMathsRandom " + (end - start));

    }

}
bdkopen
  • 494
  • 1
  • 6
  • 16
  • 1
    In the second loop you check for >= 50, which is true in more than 50% of the cases. That will cause this if statement to be true most of the times, which makes it more predictable. Your results are therefore biased in favour of your answer – Neuron Oct 24 '15 at 00:11
  • it is typo mistake...make 128 in second example you will get same result. – jatin Goyal Oct 25 '15 at 02:46