2010-09-17 116 views
4

我期待随机化BigInteger。其目的是从1到8180385048之间挑选一个数字。但是,从我注意到的BigInteger(BitLen,Random)开始,它从n到-1,我想要一些不可预知的数字。我试图制定一种方法来做到这一点,但我一直在遇到bug,并最终屈服于这里询问。 :P有没有人有任何建议如何做到这一点?随机化BigInteger

+0

不是X^2 -1,而是2 ** bitLen -1,其中**是幂运算符。 – 2010-09-17 13:31:14

回答

5

Random.nextInt(int n)的文档看,这显然需要解决同样的问题,他们似乎认为你不可能比“如果超出范围的情况下重新采样”做得更好,但是预计惩罚可以忽略不计。

从文档:

的算法是有点棘手。它拒绝会导致不均匀分布的值(由于n不能被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  %,所以不用担心: - )

+0

谢谢。虽然,它会是“i.compareTo(max)<= 0”,因为我正在寻找一个等于或低于最大值的数字。否则,这是一个坚实的例子。 – Unrealomega 2010-09-17 14:02:00

+0

啊,对,更新。您可能还想考虑到0是一个可能的返回值...正如您所说的从1到8180385048 – aioobe 2010-09-17 14:10:45

1

创建一个循环并获得随机的BigInteger s覆盖范围的最小位长,直到获得一个范围内的数字。这应该保留随机数的分布。

+0

哪个是他的具体情况会用bitLen == 33. – 2010-09-17 13:34:29

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 
+1

这很可能会导致分布不均匀。 – 2010-09-17 18:48:06

+0

对,这很可能会导致对较小值的偏见。这可能会或可能不会与原始发布者的应用程序相关。 – Grodriguez 2010-09-17 19:31:54