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


135

是什么区别Math.random() * nRandom.nextInt(n)在那里n是一个整数?


我不知道数学,但是我知道如果您使用FindBugs会抱怨Math.random()
finnw 2010年

3
请记住,Random没有静态方法,因此请使用:(new Random())。nextInt(n))。为了使Math生成类似的整数,请使用:Math.floor((Math.random()* n)+1);
Dimitri Dewaele 2014年

Answers:


169

这是Gili链接到的Sun论坛帖子中为什么“ 比“ 效率更高,偏见更少的详细说明Random.nextInt(n)Math.random() * n

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

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

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

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

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

您将要等待很长时间才能看到这种效果。

Math.random()还需要大约两次处理,并且需要进行同步。


3
Random.nextInt和nextDouble也需要同步。
adrianos

在这种情况下,“减少偏见”是什么意思?
ΦXocę 웃 Пepeúpaツ

2
@ΦXocę웃Пepeúpaツ这只是意味着某些数字比其他数字更有可能被绘制。因为它倾向于选择一些数字而不是其他数字(因此不是完全随机或没有足够大的样本量)
福特

1
请注意,该线程的最后一条评论报告:“所描述的偏差是2 ^ 53中的一部分,但是所使用的PRNG的最大循环长度仅为2 ^ 48。因此,在应用程序中将看到的是数据基本PRNG的分布,而不是偏见。” 这将表明以下事实:两种方法是等效的
数字幻觉

1
@ΦXocę웃Пepeúpaツ在骰子立方体上替换65:将“ 5偏置”。在发现骰子出问题之前,您可以掷骰子几次。在您发现随机生成器出现问题之前,您必须进行极为复杂的彻底检查。
大卫·霍瓦特

27

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



0

根据此示例,Random.nextInt(n)其可预测的输出比Math.random()* n小。根据[排序数组比未排序数组快] [1],我认为我们可以说Random.nextInt(n)很难预测

usingRandomClass:时间:328英里。

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

    }

}

1
在第二个循环中,检查> = 50,这在50%以上的情况下都是正确的。多数情况下,这会使if语句为真,从而使其更具可预测性。因此,您的结果将偏向于您的答案
Neuron 2015年

这是错别字错误...在第二个示例中输入128,您将得到相同的结果。
贾汀·戈亚尔(Jatin Goyal)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.