我使用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个值和所使用的公式,我们就可以很容易地知道第三个值,而知道要使用的公式。
答案 0 :(得分: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
是二的幂bound
不是2的幂,并且循环在第一次迭代时终止bound
不是2的幂,并且循环将持续到第一次迭代之后以2的幂数bound
的情况很容易-只需尝试适合bound
的所有以2的幂数int
即可。只有31个。您可以对此进行优化,但是没有太多意义。
可以通过计算next(31)
本来可以得到的值来处理第一个迭代的非二次方幂情况(可以通过播种Random
实例并调用{{1 }}),然后查看next(31)
的值将同时给出bound
的正确值并终止do-while。
要给出正确的值val
,val
必须比bound
大bits - val
倍。 (有时val
将为0,并且任何大于bits - val
的整数都将通过。)要终止执行,val
不得溢出。因此,在这种情况下,可能的界线是bits - val + (bound-1)
在一定范围内的因数,而不是2的幂。
对于最后一种情况,我不想经历,所以将“留给读者练习”。 (这是最困难的情况,遇到一些困难,例如弄清楚bits - val
的值会在您不知道bound
时引起溢出,这将花费比我更多的时间。)
答案 1 :(得分:0)
这是找到隐藏边界的实验方法。获取随机对象的副本并记录其输出。创建n
的{{1}}个实例,其中Random
是最大整数。对于每个n
实例,都将其索引用作Random
的参数。仅存储遵守原始序列的nextInt
实例。继续淘汰候选人,直到只剩下一个。
请参阅下表。在最上面,我们用对随机值进行采样的迭代为列命名。在一侧,我们有具有相同种子的序列,这些序列具有不同的绑定值。中间单元格中的值表示为给定的Random实例和迭代检索的随机值。
在第一次遍历所有可能的整数之后,我们剩下4个可能的候选项。我们将继续与权威机构进行比较,直到仅剩下一名可能的候选人。如果您没有从权威机构提供足够的样本,则可能会留下多个匹配的上限值候选。
Random
这将产生输出:
public static void main(String [] args) throws Exception {
final Scanner scanner = new Scanner(System.in);
System.out.print("Please enter the seed number: ");
final long seed = scanner.nextLong();
System.out.print("Please enter the hidden bound: ");
final int bound = scanner.nextInt();
final long start = System.nanoTime();
final IntSupplier original = rand(seed, bound);
final int firstRandom = original.getAsInt();
Map<Integer, IntSupplier> candidates = new HashMap<>();
for (int i = 1; i < Integer.MAX_VALUE; i++) {
final IntSupplier candidate = rand(seed, i);
if (firstRandom == candidate.getAsInt()) {
candidates.put(i, candidate);
}
}
int iterations = 1;
while (candidates.size() > 1) {
iterations += 1;
final int current = original.getAsInt();
Map<Integer, IntSupplier> survivors = new HashMap<>();
for (Map.Entry<Integer, IntSupplier> entry : candidates.entrySet()) {
if (entry.getValue().getAsInt() == current) {
survivors.put(entry.getKey(), entry.getValue());
}
}
candidates = survivors;
}
if (candidates.size() == 1) {
System.out.println("Upper bound is " + candidates.keySet().iterator().next());
} else {
System.out.println("No upper bound found");
}
System.out.println("Completed in " + iterations + " iterations");
final long end = System.nanoTime();
System.out.println("Completed in " + (end - start) / Math.pow(10,9) + "seconds");
}
static IntSupplier rand(long seed, int bound) {
final Random rand = new Random(seed);
return () -> rand.nextInt(bound);
}