随机化一个 BigInteger

发布于 2024-09-19 16:13:41 字数 189 浏览 9 评论 0原文

我正在寻找随机化一个 BigInteger。目的是从 1 到 8180385048 中选择一个数字。虽然,据我观察,BigInteger(BitLen, Random) 是从 n 到 X2-1,但我想要一些不可预测的数字。我试图制作一种可以做到这一点的方法,但我不断遇到错误,并最终屈服于在这里询问。 :P 有人对如何做到这一点有任何建议吗?

I'm looking to randomize a BigInteger. The intent is to pick a number from 1 to 8180385048. Though, from what I noticed, the BigInteger(BitLen, Random) does it from n to X2-1, I'd want some unpredictable number. I tried to make a method that would do it, but I keep running into bugs and have finally given in to asking on here. :P Does anyone have any suggestions on how to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吾性傲以野 2024-09-26 16:13:41

Random.nextInt(int n) 显然需要解决同样的问题,他们似乎得出的结论是,你不能比“超出范围时重新采样”做得更好,但是预计处罚可以忽略不计。

来自文档:

该算法有点棘手。它拒绝会导致分布不均匀的值(因为 231 不能被 n 整除)。某个值被拒绝的概率取决于 n。最坏的情况是 n=230+1,此时拒绝的概率为 1/2,循环终止前的预期迭代次数为 2。

建议您只需使用 随机化构造函数并迭代,直到达到范围内的值,例如如下所示:

public static BigInteger rndBigInt(BigInteger max) {
    Random rnd = new Random();
    do {
        BigInteger i = new BigInteger(max.bitLength(), rnd);
        if (i.compareTo(max) <= 0)
            return i;
    } while (true);
}

public static void main(String... args) {
    System.out.println(rndBigInt(new BigInteger("8180385048")));
}

对于您的特定情况(最大值= 8180385048),必须的概率重申一次,大约是 4.8%,所以不用担心:-)

Judging from the docs of Random.nextInt(int n) which obviously needs to solve the same problem, they seem to have concluded that you can't do better than "resampling if out of range", but that the penalty is expected to be negligible.

From the docs:

The algorithm is slightly tricky. It rejects values that would result in an uneven distribution (due to the fact that 231 is not divisible by n). The probability of a value being rejected depends on n. The worst case is n=230+1, for which the probability of a reject is 1/2, and the expected number of iterations before the loop terminates is 2.

I'd suggest you simply use the randomizing constructor you mentioned and iterate until you reach a value that is in range, for instance like this:

public static BigInteger rndBigInt(BigInteger max) {
    Random rnd = new Random();
    do {
        BigInteger i = new BigInteger(max.bitLength(), rnd);
        if (i.compareTo(max) <= 0)
            return i;
    } while (true);
}

public static void main(String... args) {
    System.out.println(rndBigInt(new BigInteger("8180385048")));
}

For your particular case (with max = 8180385048), the probability of having to reiterate, even once, is about 4.8 %, so no worries :-)

﹉夏雨初晴づ 2024-09-26 16:13:41

进行一个循环并随机获取涵盖范围的最小位长度的 BigInteger,直到获得范围内的一个数字。这应该保留随机数的分布。

Make a loop and get random BigIntegers of the minimum bit length that covers your range until you obtain one number in range. That should preserve the distribution of random numbers.

深海少女心 2024-09-26 16:13:41

正如其他答案中所建议的,如果超出范围,则重申是解决此问题的方法。但是,如果您想避免这种情况,另一种选择是使用模运算符:

BigInteger i = new BigInteger(max.bitLength(), rnd);
i = i.mod(max);                 // Now 0 <= i <= max - 1
i = i.add(BigInteger.ONE);      // Now 1 <= i <= max

Reiterating if out of range, as suggested in other answers, is a solution to this problem. However if you want to avoid this, another option is to use the modulus operator:

BigInteger i = new BigInteger(max.bitLength(), rnd);
i = i.mod(max);                 // Now 0 <= i <= max - 1
i = i.add(BigInteger.ONE);      // Now 1 <= i <= max
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文