Java随机总是返回相同的数字,当我设置种子?
我需要一个随机数发生器,我正在创build的帮助。 我的代码如下(在一个名为数字的类中):
public int random(int i){ Random randnum = new Random(); randnum.setSeed(123456789); return randnum.nextInt(i); }
当我从另一个类调用这个方法(为了生成一个随机数),它总是返回相同的数字。 例如,如果我这样做:
System.out.println(numbers.random(10)); System.out.print(numbers.random(10));
它总是打印相同的数字,例如5 5.我该怎么做才能打印两个不同的数字,例如5 8
种子是强制性的。
谢谢
你需要在整个类中共享Random()
实例:
public class Numbers { Random randnum; public Numbers() { randnum = new Random(); randnum.setSeed(123456789); } public int random(int i){ return randnum.nextInt(i); } }
如果你总是设置种子,你将永远得到相同的答案。 这就是种子的设置。
有两个问题引起你所看到的。 首先是代码为Random实例设置种子值。 其次是实例方法“随机”实例一个新的随机对象,然后立即设置其种子每次相同的种子。 这两个组合保证了,对于相同的值i,“随机”方法将始终返回相同的值,并始终是种子始终生成的序列中的第一个。
假设设置种子是强制性的,为了获得序列中的下一个值,而不是每次序列的相同的第一个值,Random的每个实例在每次调用其下一个方法之前都不能设置其种子。 要解决这个问题,将随机实例方法范围内的Random的randnum局部variables实例移动到类作用域。 其次,只有在随机分配一个随机实例或者只是为了得到相同的结果序列才能重新开始时,设置种子。 Class 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
如上所述,以上将给你一个确切的解决scheme,以确切的问题。 然而,使用强制种子似乎是不寻常的,因为它做了什么。
如果这是一个项目或软件testing的序列必须是可预测和可重复的,将种子设置为固定值是有道理的。 否则,质疑将种子设置为某个预定值的有效性。 以下解释更多关于随机,随机种子和为什么有提供种子的规定。
随机有两个构造函数:
Random()
和
Random(long seed)
和一个实例方法
setSeed(long seed)
所有这些都会影响从随机实例获得的数字序列。 实例方法,
setSeed(long seed)
将Random对象设置为与已经使用与构造函数参数相同的种子实例化的相同状态。 只有一个种子值的低阶48位被使用。
如果Random对象的实例没有种子,则种子将与系统时间(以毫秒为单位)相同。 这确保了,除非两个Random对象在同一个毫秒内被实例化,否则它们将产生不同的伪随机序列。 只有种子值的低位48位被使用。 这导致不可预知的伪随机序列。 每次调用下一个方法时,都不需要浪费计算资源来获取Random的新实例。
提供Random的种子参数,以便可以实例化一个Random对象,该对象产生一个可重复的序列。 对于给定的种子,无论何时使用种子,下一种方法中的值序列都保证是相同的序列。 这对testing将要使用伪随机序列的软件是有用的,其中结果必须是可预测的和可重复的。 在操作中创build不同的不可预知的伪随机序列是没有用的。
“设置种子是强制性的”声明否定了随机对象的伪随机序列的任何不可预知性。 这是用于课程项目还是软件testing,结果必须与程序的相同input相同?
在启动时设置种子一次,而不是每次你想要一个新的随机数。
你正在使用的不是一个随机数发生器,它是一个伪随机数发生器。 PRNG生成伪随机数序列,种子select一个序列中的一个起点(一个PRNG可以产生一个或几个序列)。
你是否需要在你的random(int i)
方法中创buildnew Random()
? 如果你有义务这样做,你可以使用,你可以设置种子到当前时间,虽然这不是失败的certificate,因为你可以打电话给你的numbers.random(10)
如此之快,最终成为同一颗种子。 你可以尝试使用nanoSeconds(System.nanoTime()我认为?如果setSeed只接受int,乘以它我猜)。
然而,我build议,如果你被允许的话,就是在你的方法之外声明你的Random。 如果你使用你的随机variables,例如你的number
类的构造函数,你可以设置任何种子,任何时候你调用你的方法,它会给你一个新的数字。 (如果你使用一个常量种子,每次你重新启动你的应用程序时,它们都是相同的数字组,但是在这种情况下,你也可以使用时间作为你的种子)。
最后,如果你同时声明几个number
类,最后的问题可能是。 他们都有相同的随机种子,并给你相同的随机数字集。 如果发生这种情况,您可以在您的主类中创build一个static Random
,并在您的数字类中调用它。 这虽然会把这两个class级结合在一起,但是它会起作用的。 另一个select是向您的number
类构造函数发送递增值,对于您实例化的每个number
,并使用您传递的值作为种子。
如果允许你这样做的话,第二个选项应该对你有好处。
通常,Random不是真正的随机而是伪随机的。 这意味着它需要一个给定的种子,并使用它来产生一个看起来像随机的数字序列(但是是可预测的,如果你把相同的种子重复的话)。
如果你不放种子,那么第一个种子将从一个可变的来源(通常是系统时间)中获取。
通常情况下,将使用带有种子的值,以便重复确切的值(例如,用于testing)。 使用不带种子的随机数。