有两个问题导致了你所看到的情况。第一个问题是代码为Random实例设置了种子值。第二个问题是实例方法“random”每次都会实例化一个新的Random对象,然后立即使用相同的种子设置其种子。这两者的组合保证了对于相同的i值,“random”方法将始终返回相同的值,并且它将始终是种子生成的序列中的第一个值。
假设设置种子是必需的,为了获得序列中的下一个值而不是每次都获得序列的相同第一个值,randnum Random实例不能在每次调用其next方法之前都设置其种子。为了解决这个问题,将Random局部变量实例从random实例方法的范围移动到类范围。其次,只有在将random分配给Random实例或只要重新开始获取相同的结果序列时才设置种子。Random类的setSeed(long seed)实例方法无法在类范围内执行,因此构造函数必须使用带有长种子参数的Random构造函数进行设置。以下代码显示了更改:
public class RandomDemo {
private Random randnum = new Random(123456789L);
public int randnum(int i) {
return randnum.nextInt(i);
}
}
以上将根据所述的问题给出确切的解决方案。然而,使用强制种子似乎不太常见,考虑到它的作用。
如果这是一个课程项目或软件测试,其中序列必须可预测和可重复,将种子设置为固定值是有意义的。否则,应质疑将种子设置为某个预定值的有效性。以下内容更详细地解释了Random、Random种子以及为什么需要提供种子的原因。
Random有两个构造函数:
Random()
并且
Random(long seed)
以及一个实例方法
setSeed(long seed)
所有这些都会影响从Random实例中获得的数字序列。其中,实例方法,
setSeed(long seed)
将Random对象设置为与构造函数参数相同种子的状态。只使用种子值的低位48位。
如果没有指定种子,将使用系统当前时间的毫秒数作为种子。这确保了除非在同一毫秒内实例化两个Random对象,否则它们将生成不同的伪随机序列。只使用种子值的低位48位。这会导致不可预测的伪随机序列。每次调用next方法时都获取新的Random实例是不必要且浪费计算资源的。
提供Random的种子参数是为了可以实例化一个能够生成可重复序列的Random对象。对于给定的种子,next方法中的值序列在每次使用该种子时保证是相同的序列。这对于需要使用伪随机序列并需要结果可预测和可重复的软件测试非常有用。但在操作中创建不同的不可预测的伪随机序列是没有用处的。
声明“必须设置种子”否定了Random对象的伪随机序列的任何不可预测性。这是否是用于类项目或软件测试,其中程序的输入相同时结果必须相同?