我使用Java中的种子生成随机数。知道最终的输出是235,种子编号是532,如何在Java中获取intBound编号?
例如
int randomNumber
int seed=532;
int intBound=800;
Random rand = Random(seed);
randomNumber=rand.nextInt(intBound);
System.out.println("The generated Random number using the above seed and int bound is:- "+randomNumber);
//Results is: The generated Random number using the above seed and int bound is: 235
这个问题的简化数学版本是:仅知道一个数学公式的两个值,您如何产生第三个值?例如1 + 2 = 3,这也意味着,如果我们只知道2个值和所使用的公式,我们就可以很容易地获得第三个值,而无需知道获得结果所用的公式。
最佳答案
这不可能。许多上限可以产生相同的输出。例如,在Ideone上的quick test显示1000000以下的9个可能的界限,将产生带有种子532的235输出(而800不是其中之一):237、369、711、3239、9717、29151、50549、151647和454941。
import java.util.*;
class Test
{
public static void main (String[] args) throws java.lang.Exception
{
List<Integer> bounds = new ArrayList<Integer>();
for (int i = 1; i < 1000000; i++) {
Random rng = new Random(532);
if (rng.nextInt(i) == 235) {
bounds.add(i);
}
}
System.out.println(bounds);
}
}
您能做的最好的就是确定可能的界限。
nextInt(int)
的实现是required,等同于 public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException("bound must be positive");
if ((bound & -bound) == bound) // i.e., bound is a power of 2
return (int)((bound * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % bound;
} while (bits - val + (bound-1) < 0);
return val;
}
该算法提供特定输出的方式可以分为三种可能性:
bound
是2的幂bound
不是2的幂,并且循环在第一次迭代时终止bound
不是2的幂,并且循环将持续到第一次迭代之后二次幂
bound
的情况很简单-只需尝试适合bound
的每个二次幂int
。只有31个。您可以对此进行优化,但是没有太多意义。可以通过计算
next(31)
的值(可以通过播种Random
实例并调用next(31)
来完成),然后查看bound
的值来处理第一次迭代的非幂次为2的情况。 val
都将给出正确的val
值并终止do-while。要给出正确的
bound
值,bits - val
必须是val
的因数大于bits - val
的因数。 (有时val
为0,并且任何大于bits - val + (bound-1)
的整数都将通过。)要终止执行,bits - val
一定不能溢出。因此,落入这种情况的可能边界是某个范围内的bound
因子,而不是2的幂。至于最后一种情况,我不想经历,所以将“留给读者练习”。 (这是最困难的情况,遇到一些困难,例如弄清楚
val
的值会在您不知道时导致溢出,这会花费比我更多的时间。)