我想随机化一个BigInteger。目的是从1到8180385048中选择一个数字。虽然,从我注意到,BigInteger(BitLen,Random)从n到X 2 -1,我想要一些不可预测的数字。我试图制作一个可以做到这一点的方法,但是我一直遇到错误并最终放弃在这里询问。 :P有没有人对如何做这个有任何建议?
答案 0 :(得分:5)
从显然需要解决相同问题的Random.nextInt(int n)
的文档来看,他们似乎已经得出结论,你不能做得比“重新取样如果超出范围”更好,但是预计会受到惩罚可以忽略不计。
来自文档:
算法有点棘手。它拒绝会导致分布不均匀的值(由于2 31 不能被n整除)。值被拒绝的概率取决于n。最坏的情况是n = 2 30 +1,其中拒绝的概率是1/2,并且循环终止前的预期迭代次数是2.
我建议您只使用您提到的randomizing constructor并进行迭代,直到达到范围内的值,例如:
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%,所以不用担心: - )
答案 1 :(得分:1)
进行循环并获得覆盖范围的最小位长度的随机BigInteger
,直到获得范围内的一个数字。这应该保留随机数的分布。
答案 2 :(得分:0)
如果在其他答案中建议,如果超出范围则重申是此问题的解决方案。但是,如果您想避免这种情况,另一种选择是使用模数运算符:
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