Java随机序列

3
让我尽力解释一下我的问题,我们有一个使用特定种子构造的Random 类。此时,我们可以使用 .next() 方法获得从种子派生的下一个值。
我似乎需要一种方法来获取这个序列中的值,但不按顺序。例如,如果 Random 有一个像 .get(X) 这样的方法,它将返回在第 X 次调用 .next() 时得到的任何值。
我能想到的一种方法是使用一个 for 循环 X 次,在每个周期上调用 .next(),但不给变量赋值。这不会很好地工作,因为 A. 性能和 B. 它将 Random 序列保留在 X(如果下一个 X 小于原始 X,则必须重新构造 Random)。
这里是我想到的另一种解决这个问题的方法。也许你可以从旧种子和 X 中派生出一个临时新种子,调用一次 next() 并存储值,然后将 Random 返回到其原始种子。我不知道从两个值中获取这个新种子的典型方法,可能是一些疯狂的位运算。我对这种方法的所有实验都不够随机。
谢谢你的帮助!

1
你正在追逐一个虚假的目标。在一个良好的随机生成器中,.next() 和 .get(X) 是不可区分的。如果标准的 Random 对你足够好,那么你不需要使用 .get(X)。如果不行,那么 .get(X) 和 .next() 一样糟糕。 - Alexei Kaigorodov
你是如何得出使用for循环方法会因性能和(B)原因而无法工作的结论的? - swapnil7
1
没有关闭的绝对理由。完美的问题。 - Basilevs
2个回答

4
您可以为您的随机对象创建一个缓存。我的意思是创建一个最初为空的ArrayList。然后创建get(X)方法,该方法同时使用ArrayList和Random对象。当调用get(X)时,您调用Random的next()方法X次,并将其生成的X个值写入ArrayList中。然后返回最后一个值。
下一次使用参数Y调用get()时,您将Y与ArrayList的长度进行比较。如果它小于列表的长度(Y小于X),则您已经计算过该值,可以在ArrayList中查找并返回它。如果Y大于列表的长度,则通过调用Random的next()方法足够多次以达到Y来增加ArrayList的大小。
您需要一些内存,但它会让您回到之前的状态,运行时间将慢于您曾经见过的最大X。

1
一个更简单的方法是预先生成一堆随机数(尽可能多地生成你在程序中需要的数量),并将它们存储在一个数组中。当你需要这些随机数时,只需在数组中查找即可。 - Abednego
那是个好主意,到目前为止我当然最喜欢你的。我确实进行了一些搜索,并找到了这个类似的(我认为,不确定他的目的是否接近我的)问题:bit.ly/1hu6T59 你认为那个答案中的代码能给我想要的效果吗? - Joe Johnson

-2
我的一个朋友曾经告诉我,计算机中实际上无法产生随机值,因为任何随机值生成方法都基于逻辑算法。
import java.util.Random;

Random random = new Random(System.currentTimeMillis());

// Example
int randomInt = random.nextInt(500); [Returns value between 0(inclusive) and 500 (exclusive)]
And so goes the other methods.

由于时间不会重复,调用System.currentTimeMillis()并将其作为随机种子传递可能是最好的选择。这是最常见的做法。

无论你使用什么算法,你仍然会得到一个伪随机数。
你必须观察一个物理过程来获取真正的随机数。


-1 该问题询问的是关于预先设定的序列生成器,没有要求物理上的随机性。 - Basilevs
请仔细阅读问题,种子“不应该”是随机的! - Basilevs
时间种子从什么时候开始变得随机了? :D 但是说实话,我无法在问题中看到任何地方,OP已经说过种子不应该是随机的。 - Aman Agnihotri
假设我们有一个使用特定种子构造的Random类,执行时间有多具体? - Basilevs
是的,“特定种子”意味着(在我看来)程序员指定的任何种子。我的真诚意见是,System.currentTimeMillis() 是程序员可以提供的最好的种子之一,因为时间永远不会重复。然后可以通过它生成预先种子化的序列。 - Aman Agnihotri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接