Java Math.random() 与 Random.nextInt(int)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/738629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:54:19  来源:igfitidea点击:

Math.random() versus Random.nextInt(int)

javarandom

提问by Gili

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

整数Math.random() * nRandom.nextInt(n)wheren有什么区别?

采纳答案by matt b

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

以下是Gili 链接到的 Sun 论坛帖子中关于“比”更有效且更不偏向的原因的详细解释Random.nextInt(n)Math.random() * n

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.

Math.random() 在内部使用 Random.nextDouble()。

Random.nextDouble() 使用 Random.next() 两次来生成一个 double,它的尾数位近似均匀分布,因此它在 0 到 1-(2^-53) 范围内均匀分布。

Random.nextInt(n) 使用 Random.next() 平均少于两次 - 它使用它一次,如果获得的值高于 MAX_INT 以下的 n 的最高倍数,则再次尝试,否则返回模 n 的值(这防止高于 n 的最高倍数低于 MAX_INT 的值扭曲分布),因此返回一个在 0 到 n-1 范围内均匀分布的值。

在按比例缩放 6 之前,Math.random() 的输出是从均匀分布中抽取的 2^53 个可能值之一。

按 6 缩放不会改变可能值的数量,并且转换为 int 然后将这些值强制放入六个“桶”(0、1、2、3、4、5)之一,每个桶对应于包含其中之一的范围可能值的 1501199875790165 或 1501199875790166(因为 6 不是 2^53 的除数)。这意味着对于足够数量的骰子(或具有足够多边的骰子),骰子将显示自己偏向较大的桶。

您将等待很长时间掷骰子才能显示此效果。

Math.random() 也需要大约两倍的处理,并且需要同步。

回答by Gili

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

根据https://forums.oracle.com/forums/thread.jspa?messageID=6594485龵Random.nextInt(n)Math.random() * n

回答by dfa

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

另一个重点是 Random.nextInt(n) 是可重复的,因为您可以使用相同的种子创建两个 Random 对象。这对于 Math.random() 是不可能的。

回答by jatin Goyal

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.

根据这个例子,Random.nextInt(n)输出的可预测性低于 Math.random() * n。根据 [排序数组比未排序数组更快][1] 我认为我们可以说 Random.nextInt(n)很难预测

usingRandomClass : time:328milesecond.

usingRandomClass:时间:328英里。

usingMathsRandom : time:187milesecond.

usingMathsRandom:时间:187英里。

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));

    }

}