当我设置种子时,Java随机总是返回相同的数字?

bad*_*der 21 java random

我需要帮助我正在创建的随机数生成器.我的代码如下(在一个名为numbers的类中):

public int random(int i){
    Random randnum = new Random();
    randnum.setSeed(123456789);
    return randnum.nextInt(i);
}
Run Code Online (Sandbox Code Playgroud)

当我从另一个类调用此方法时(为了生成一个随机数),它总是返回相同的数字.例如,如果我这样做:

System.out.println(numbers.random(10));
System.out.print(numbers.random(10));
Run Code Online (Sandbox Code Playgroud)

它总是打印相同的数字,例如5 5.我需要做什么才能打印两个不同的数字,例如5 8

我必须设置种子.

谢谢

Sop*_*ert 47

您需要Random()在整个班级中共享实例:

public class Numbers {
    Random randnum;

    public Numbers() {
        randnum = new Random();
        randnum.setSeed(123456789);
    }

    public int random(int i){
        return randnum.nextInt(i);
    }
}
Run Code Online (Sandbox Code Playgroud)


Oli*_*rth 36

如果您始终设置种子,您将始终得到相同的答案.这就是种子的设定.


Jim*_*Jim 14

导致您看到的内容有两个问题.第一个是代码为Random实例设置种子值.第二个是实例方法"random"实例化一个新的Random对象,然后每次立即使用相同的种子设置其种子.这两者的组合保证,对于i的相同值,方法"random"将始终返回相同的值,并且它将始终是种子始终生成的序列中的第一个.

假设设置种子是必需的,为了获得序列中的下一个值而不是每次都获得序列的相同第一个值,Random的randnum实例每次在其下一个方法被调用之前都不能设置其种子集.要解决此问题,请将Random的randnum局部变量实例从随机实例方法的范围移动到类范围.其次,仅在为随机分配一个Random实例时设置种子,或者仅为了从中获取相同的结果序列以重新开始.Random Random的setSeed(long seed)实例方法无法在类范围内执行,因此构造函数必须使用带有long种子参数的Random构造函数来设置它.以下代码显示了更改:

public class RandomDemo { // arbitrary example class name
    // lots of class related stuff may be here...

    // still inside the class scope...
    // private is a good idea unless an external method needs to change it
    private Random randnum = new Random(123456789L);
    // the seed guarantees it will always produce the same sequence
    // of pseudo-random values when the next methods get called
    // for unpredicable sequences, use the following constructor instead:
    // private Random randnum = new Random();

    // lots of code may be here...

    // publicly exposed instance method for getting random number
    // from a sequence determined by seed 123456789L
    // in the range from 0 through i-1
    public int randnum(int i) {
        // don't set the seed in here, or randnum will return the exact same integer
        // for the same value of i on every method call
        // nextInt(i) will give the next value from randnum conforming to range i
        return randnum.nextInt(i);
    } // end randnum

    // lots of more code may be here...

} // end class RandDemo
Run Code Online (Sandbox Code Playgroud)

如上所述,上述内容将为您提供确切问题的精确解决方案.然而,鉴于它的作用,使用强制种子似乎是不寻常的.

如果这是一个类项目或软件测试,其中序列必须是可预测和可重复的,那么将种子设置为固定值是有意义的.否则,质疑将种子设置为某个预定值的有效性.以下解释更多关于随机种子,随机种子以及为何提供种子的规定.

Random有两个构造函数:

Random()
Run Code Online (Sandbox Code Playgroud)

Random(long seed)
Run Code Online (Sandbox Code Playgroud)

和一个实例方法

setSeed(long seed)
Run Code Online (Sandbox Code Playgroud)

这些都会影响从Random实例获得的数字序列.实例方法,

setSeed(long seed)
Run Code Online (Sandbox Code Playgroud)

将Random对象设置为与它刚刚使用与构造函数参数相同的种子实例化时所处的状态.仅使用种子值的低48位.

如果在没有种子的情况下实例化Random对象,则种子将与系统时间相同(以毫秒为单位).这确保了,除非两个Random对象在相同的毫秒内实例化,否则它们将产生不同的伪随机序列.仅使用种子值的低48位.这导致不可预测的伪随机序列.每次调用下一个方法时,都不需要浪费计算资源来获取Random的新实例.

提供Random的种子参数,以便可以实例化一个产生可重复序列的Random对象.对于给定的种子,无论何时使用该种子,下一种方法中的值序列都保证是相同的序列.这对于测试将使用伪随机序列的软件非常有用,其中结果必须是可预测且可重复的.在操作中创建不同的不可预测的伪随机序列是没有用的.

声明"我必须设置种子"否定了Random对象的伪随机序列的任何不可预测性.这是针对类项目还是软件测试,其中对于程序的相同输入,结果必须相同?