/**
* Mimics the {@link BigInteger#BigInteger(int, Random)} function using a
* {@link RandomGenerator} instance.
*
* @param numBits maximum bitLength of the new BigInteger.
* @param rnd source of randomness to be used in computing the new
* BigInteger.
* @throws IllegalArgumentException {@code numBits} is negative.
* @see #bitLength()
*/
public static BigInteger generateRandomBigInteger(int numBits, RandomGenerator rng) {
if (numBits < 0) {
throw new IllegalArgumentException("numBits must be non-negative");
}
if (numBits == 0) {
return BigInteger.ZERO;
}
int bytes = (numBits + Byte.SIZE - 1) / Byte.SIZE;
// mask bits that we need the value of to 1, the others - if any -- will be set
// to zero
byte bitMask = (byte) ((1 << ((numBits - 1) % Byte.SIZE + 1)) - 1);
byte[] randomBytes = new byte[bytes];
rng.nextBytes(randomBytes);
randomBytes[0] &= bitMask;
return new BigInteger(1, randomBytes);
}
1条答案
按热度按时间bf1o4zei1#
只是使用
Random
和SecureRandom
为什么需要这个?因为
new Random()
为您提供了一个相对快速的非安全随机数生成器,而new SecureRandom()
提供了一个CSPRNG(加密安全伪随机数生成器)。* 这两个示例都是RandomGenerator
接口的示例。* 因此,只有当您希望在随机包中定义特定的随机数生成器时,才需要这个。如果您不需要速度,也没有任何关于发行版的特定需求-如果您有任何需求,您可能会知道-那么请使用
new BigInteger(n, new SecureRandom())
。实施
Random
TL;DR:不要
Random
类已经被重构为一个实现接口的类。这意味着你可以在接口指定RandomGenerator
的任何地方使用旧的Random
。然而,这并不能反过来工作。Random
本身不是final
类,所以可以从继承,所以可以原则上通过简单地实现Random
中的所有方法并调用 Package 的RandomGenerator
的类似命名的方法来创建适配器类。然而,这是非常危险的做法,因为Random
的未来扩展可能会破坏一切。在最坏的情况下,它将通过混合父Random
对象和 Package 的RandomGenerator
的状态来显示不一致的行为。迁移到Java 19
在Java 19(构建版本b21)中,为
RandomGenerator
提供了一个适配器方法,名为Random#from(RandomGenerator)
,您可以看到特性请求here。优选地,X1 M20 N1 X方法应当被改进以使用X1 M21 N1 X(如特征请求中所述)。注意如果你怀疑
setSeed
可能被调用,你应该 * 永远不要 * 使用这个 Package 类,例如当在BigInteger
类中生成一个大素数时。如果它被调用,它将生成一个UnsupportedOperationException
。这类类类经过了各种测试,因此Java提供的方法是可信的。然而,一个方法可以被改造以使用
setSeed
的事实可能是一个关于向前兼容性的问题--你已经被警告过了。[0, n^2)
的特例但是,你已经有一个了:范围
0..2^n-1
或[0, 2^n-1)
是一个由一组位组成的数,所以你可以使用你的RandomGenerator
,填充一个字节数组,从第一个字节中删除最重要的位(因为Java是big endian),然后将数组转换成一个有符号整数:numBits
当然与您的n
变量相同。[0,max)的大小写
实际上,您可以将比较函数和随机位生成器组合在一起,这样您就可以创建范围为0..max的大随机值,其中max具有 * 任意值 *,随机位的数量最少,并且根本不需要讨厌的
BigInteger
操作(例如除法)。你可以找到我对那个here的实现,但你可能会觉得奇怪。事先抱歉,是的,这是我的RNGBC算法的无耻插件:)