2 回答

TA貢獻1777條經驗 獲得超10個贊
這不可能。許多上限可以產生相同的輸出。例如,對 Ideone的快速測試顯示了 1000000 下的 9 個可能邊界,這將產生 235 的輸出,種子 532(800 不是其中之一):237、369、711、3239、9717、29151、505164、155164、15164和 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)是需要等同于
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 的冪,循環繼續經過第一次迭代
二的冪的bound
情況很容易 - 只需嘗試bound
適合int
. 其中只有31個。你可以優化這個,但沒有多大意義。
可以通過計算next(31)
本來是的值(可以通過播種一個Random
實例并調用next(31)
)來處理第一次迭代的非二次冪情況,然后查看哪些值bound
會給出正確的值val
并終止做的時候。
要給出 的正確值val
,bound
必須是一個bits - val
大于的因數val
。(有時bits - val
會是 0,任何大于它的整數val
都會通過。)要終止 do-while,bits - val + (bound-1)
一定不能溢出。因此,落入這種情況的可能界限bits - val
是一定范圍內的因子,而不是 2 的冪。
至于最后一個案例,我不想經歷它,所以這將“留給讀者作為練習”。(這是最困難的情況,困難在于弄清楚bound
當您不知道時哪些值會導致溢出val
,而這比我花費的時間更長。)

TA貢獻1815條經驗 獲得超10個贊
這是一種尋找隱藏邊界的實驗方法。獲取隨機對象的副本并記錄其輸出。創建where is max int 的n
實例。對于這些實例中的每一個,使用它們的索引作為 的參數。僅存儲遵循原始序列的實例。繼續淘汰候選人,直到只剩下一個。Random
n
Random
nextInt
Random
考慮下表。在頂部,我們使用隨機值被采樣的迭代來命名列。另一方面,我們有具有相同種子的序列,它們應用了不同的邊界值。中間單元格中的值表示為給定的 Random 實例和迭代檢索到的隨機值。
在第一次遍歷所有可能的整數后,我們剩下 4 個可能的候選者。我們不斷與權威進行比較,直到只剩下一個可能的候選人為止。如果您沒有提供足夠的權威樣本,您可能會留下多個匹配的上限值候選。
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);
}
這會產生輸出:
Please enter the seed number: 532
Please enter the hidden bound: 800
Upper bound is 800
Completed in 4 iterations
Completed in 46.778499624 seconds
添加回答
舉報