Java如何产生一个随机数?

Java如何产生一个随机数?,java,random,Java,Random,我知道你可以使用Java中的Math.random()生成一个从0.0到1.0的随机双精度数,但是计算机如何选择一个数字呢?计算机遵循什么代码来模拟随机性 您可以在Java类声明中找到它。这个来自Math.class: public static double random() { return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); } 在Eclipse中很容易做到这一点。焦点&F3。您可以在Ja

我知道你可以使用Java中的Math.random()生成一个从0.0到1.0的随机双精度数,但是计算机如何选择一个数字呢?计算机遵循什么代码来模拟随机性

您可以在Java类声明中找到它。这个来自Math.class:

public static double random() {
    return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}

在Eclipse中很容易做到这一点。焦点&F3。

您可以在Java类声明中找到它。这个来自Math.class:

public static double random() {
    return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}

在Eclipse中很容易做到这一点。关注&F3。

关于随机数的真相是它们不是真正的随机数。它们只是以毫秒/纳米(甚至更少)为单位计算当前时间。。。因为时间总是变化的,从不重复,所以这个值不可能是同一个值,因为“同一个原因”使得随机数成为随机数

查看@FranciscoSpaeth答案:


关于随机数的真相是它们不是真正的随机数。它们只是以毫秒/纳米(甚至更少)为单位计算当前时间。。。因为时间总是变化的,从不重复,所以这个值不可能是同一个值,因为“同一个原因”使得随机数成为随机数

查看@FranciscoSpaeth答案:


通过查看文档很容易找到,因为令人高兴的是,行为在Java中定义良好。从

当第一次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式一样

new java.util.Random()

遗憾的是,它没有明确说明它调用
Random
上的哪个方法。但是,由于其返回值与它在“另请参阅”部分中链接的
Random.nextDouble
在同一范围内,因此应该安全地假设使用的是该值

看着

在哪里

随机数生成器的种子[被初始化为]一个很可能不同于此构造函数的任何其他调用的值


通过观察这一点,应该很清楚,事实上,这个数字并不像大多数人所理解的那样是“随机的”。这是一个完全可预测的数学模式,被称为,它对于许多目的来说都是随机的。但是,根据您希望结果的不可预测性,它可能值得研究(这会产生不可预测的、加密性强的随机值)。

这很容易通过查看文档找到,因为令人高兴的是,行为在Java中定义良好。从

当第一次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式一样

new java.util.Random()

遗憾的是,它没有明确说明它调用
Random
上的哪个方法。但是,由于其返回值与它在“另请参阅”部分中链接的
Random.nextDouble
在同一范围内,因此应该安全地假设使用的是该值

看着

在哪里

随机数生成器的种子[被初始化为]一个很可能不同于此构造函数的任何其他调用的值


通过观察这一点,应该很清楚,事实上,这个数字并不像大多数人所理解的那样是“随机的”。这是一个完全可预测的数学模式,被称为,它对于许多目的来说都是随机的。但是,根据您希望结果的不可预测性,它可能值得研究(这会产生不可预测的加密强随机值)。

通过查看java中random类的源代码,您会发现这取决于您是否使用种子,即调用public random()或调用public random()(长种子)

来自Java Random类的源代码:

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 1181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

private static final AtomicLong seedUniquifier
    = new AtomicLong(8682522807148012L);
您可以看到,如果不指定种子,则类Random将使用原子长种子并使用System.nanoTime()执行按位异或操作(^)

但是,如果确实指定了种子,则会调用代码的另一部分,而不调用System.nanoTime()

(请注意,如果在没有种子的情况下调用,则使用种子的构造函数将被称为nontheless,但其种子由System.nanoTime()组成,这保证了每次调用都有不同的种子)

首先通过调用initialScramble(长种子)方法对种子进行加扰

通过nextBytes、nextLong、nextInt等从代码中调用,调用next(),其实现如下:

 protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
    oldseed = seed.get();
    nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}
它基本上包含行中的“线性同余生成器”

nextseed = (oldseed * multiplier + addend) & mask;
您可以测试带种子和不带种子的调用之间的差异。如果提供种子并仅调用一次方法nextInt、nextBytes等,则每次都将获得相同的值。
但是,如果不指定种子,即使只调用一次方法nextInt、nextBytes等,也会得到不同的值。

通过查看java中Random类的源代码,您会发现这取决于是否使用种子,即调用public Random()或调用public Random(长种子)

来自Java Random类的源代码:

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 1181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

private static final AtomicLong seedUniquifier
    = new AtomicLong(8682522807148012L);
您可以看到,如果不指定种子,则类Random将使用原子长种子并使用System.nanoTime()执行按位异或操作(^)

但是,如果确实指定了种子,则会调用代码的另一部分,而不调用System.nanoTime()

(请注意,如果在没有种子的情况下调用,则使用种子的构造函数将被称为nontheless,但其种子由System.nanoTime()组成,这保证了每次调用都有不同的种子)

首先通过调用initialScramble(长种子)方法对种子进行加扰

通过nextBytes、nextLong、nextInt等从代码中调用,调用next(),其实现如下:

 protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
    oldseed = seed.get();
    nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}
它基本上包含行中的“线性同余生成器”

nextseed = (oldseed * multiplier + addend) & mask;
您可以测试带有和不带种子的调用之间的差异