为了账号安全,请及时绑定邮箱和手机立即绑定

如何获得用于生成随机数的范围?

如何获得用于生成随机数的范围?

蛊毒传说 2021-12-30 16:17:50
我使用 Java 中的种子生成随机数。知道最终输出是235,种子数是532,我如何在java中得到intBound数?例如int randomNumberint 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 个值和使用的公式,我们可以很容易地得到第三个值,知道用于获得结果的公式。
查看完整描述

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并终止做的时候。

要给出 的正确值valbound必须是一个bits - val大于的因数val。(有时bits - val会是 0,任何大于它的整数val都会通过。)要终止 do-while,bits - val + (bound-1)一定不能溢出。因此,落入这种情况的可能界限bits - val是一定范围内的因子,而不是 2 的幂。

至于最后一个案例,我不想经历它,所以这将“留给读者作为练习”。(这是最困难的情况,困难在于弄清楚bound当您不知道时哪些值会导致溢出val,而这比我花费的时间更长。)


查看完整回答
反对 回复 2021-12-30
?
动漫人物

TA贡献1815条经验 获得超10个赞

这是一种寻找隐藏边界的实验方法。获取随机对象的副本并记录其输出。创建where is max int 的n实例。对于这些实例中的每一个,使用它们的索引作为 的参数。仅存储遵循原始序列的实例。继续淘汰候选人,直到只剩下一个。RandomnRandomnextIntRandom

考虑下表。在顶部,我们使用随机值被采样的迭代来命名列。另一方面,我们有具有相同种子的序列,它们应用了不同的边界值。中间单元格中的值表示为给定的 Random 实例和迭代检索到的随机值。

在第一次遍历所有可能的整数后,我们剩下 4 个可能的候选者。我们不断与权威进行比较,直到只剩下一个可能的候选人为止。如果您没有提供足够的权威样本,您可能会留下多个匹配的上限值候选。

//img1.sycdn.imooc.com//61cd6b5900011e8209450224.jpg

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


查看完整回答
反对 回复 2021-12-30
  • 2 回答
  • 0 关注
  • 154 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信