我使用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的值会在您不知道时导致溢出,这会花费比我更多的时间。)

09-26 20:33