Java 中大数的更快 mod 运算
Faster mod operation for large numbers in Java
我需要检查 X 是否可以被 Y 整除。在其他情况下我不需要实际余数。
我正在使用 "mod" 运算符。
if (X.mod(Y).equals(BigInteger.ZERO))
{
do something
}
现在,我只对 X 能被 Y 整除感兴趣,我不需要其他情况下的实际余数。
寻找一种更快的方法来检查股息固定时的可分性。更准确地说,在进行 Lucas-Lehmer 测试之前检查具有许多较小素数的大数(可能是素数)。
我只是想知道,我们能否根据 X 和 Y 的最后一位或两位数字做出一些假设(向前看类型),然后我们可以决定是否选择 mod(当没有机会得到零时)。
有一些算法可以检查整除性,但它是复数形式,并且每个算法都涵盖一组特定的数字,例如可被 3 整除,可被 4 整除等。可以找到一些算法的列表,例如在 Wikipedia。没有通用的、高性能的算法可以用于任何给定的数字,否则发现它的人会很有名,并且那里的每一个可除法实现都会使用它。
Java BigInteger
s(就像 1980 年左右以来计算机中的大多数数字一样)是二进制的,因此唯一可以通过查看最后一个 'digits'(二进制数字)来优化的模数= bits) 是 2 的幂,而 2 的唯一幂是素数是 21。 BigInteger.testBit(0)
直接测试。然而,大多数生成大 should-be 素数的软件都用于密码学(如 RSA、Rabin、DH、DSA),并确保从一开始就不会测试偶数候选;参见例如FIPS186-4 A.1.1.2(或更早版本)。
由于你的实际目标不是如标题所述,而是测试一个(大)整数是否不能被几个小素数的any整除,数学上最快的方法是形成它们的乘积——通常是任何公倍数,最好是最小的,但对于不同的素数,乘积 是 LCM——并使用 Euclid's algorithm.如果 GCD 为 1,则乘积中的 no 个质因数与候选者相同,从而将其分开。这需要几个 BigInteger divideAndRemainder 操作,但它可以一次性处理所有测试。
中间的方法是'bunch'几个乘积小于231或263的小素数,取BigInteger.mod
(或.remainder
)该产品分别为.intValue()
或.longValue()
,并使用int
测试(如果非零)每个小素数的整除性或 long
操作,比 BigInteger
操作快得多。如果需要,重复几束。 BigInteger.probablePrime
和相关例程正是这样做的(素数 3..41 反对 long
)对于最多 95 位的候选者,它认为 Erastosthenes-style 筛更有效。 (在任何一种情况下,后跟 Miller-Rabin 和 Lucas-Lehmer。)
在 Java 中测量此类内容时,请记住,如果您执行某些方法 'a lot',其中 'a lot' 的确切定义可能会有所不同且难以确定,所有常见的 JVM 将 JIT-compile 代码,从根本上改变性能。如果您经常这样做,请务必测量编译性能,如果您不经常这样做,则性能通常不会'没关系。关于 'microbenchmark(s)' 中 Java 的陷阱,SO 上存在 许多 个现有问题。
我需要检查 X 是否可以被 Y 整除。在其他情况下我不需要实际余数。
我正在使用 "mod" 运算符。
if (X.mod(Y).equals(BigInteger.ZERO))
{
do something
}
现在,我只对 X 能被 Y 整除感兴趣,我不需要其他情况下的实际余数。
寻找一种更快的方法来检查股息固定时的可分性。更准确地说,在进行 Lucas-Lehmer 测试之前检查具有许多较小素数的大数(可能是素数)。
我只是想知道,我们能否根据 X 和 Y 的最后一位或两位数字做出一些假设(向前看类型),然后我们可以决定是否选择 mod(当没有机会得到零时)。
有一些算法可以检查整除性,但它是复数形式,并且每个算法都涵盖一组特定的数字,例如可被 3 整除,可被 4 整除等。可以找到一些算法的列表,例如在 Wikipedia。没有通用的、高性能的算法可以用于任何给定的数字,否则发现它的人会很有名,并且那里的每一个可除法实现都会使用它。
Java BigInteger
s(就像 1980 年左右以来计算机中的大多数数字一样)是二进制的,因此唯一可以通过查看最后一个 'digits'(二进制数字)来优化的模数= bits) 是 2 的幂,而 2 的唯一幂是素数是 21。 BigInteger.testBit(0)
直接测试。然而,大多数生成大 should-be 素数的软件都用于密码学(如 RSA、Rabin、DH、DSA),并确保从一开始就不会测试偶数候选;参见例如FIPS186-4 A.1.1.2(或更早版本)。
由于你的实际目标不是如标题所述,而是测试一个(大)整数是否不能被几个小素数的any整除,数学上最快的方法是形成它们的乘积——通常是任何公倍数,最好是最小的,但对于不同的素数,乘积 是 LCM——并使用 Euclid's algorithm.如果 GCD 为 1,则乘积中的 no 个质因数与候选者相同,从而将其分开。这需要几个 BigInteger divideAndRemainder 操作,但它可以一次性处理所有测试。
中间的方法是'bunch'几个乘积小于231或263的小素数,取BigInteger.mod
(或.remainder
)该产品分别为.intValue()
或.longValue()
,并使用int
测试(如果非零)每个小素数的整除性或 long
操作,比 BigInteger
操作快得多。如果需要,重复几束。 BigInteger.probablePrime
和相关例程正是这样做的(素数 3..41 反对 long
)对于最多 95 位的候选者,它认为 Erastosthenes-style 筛更有效。 (在任何一种情况下,后跟 Miller-Rabin 和 Lucas-Lehmer。)
在 Java 中测量此类内容时,请记住,如果您执行某些方法 'a lot',其中 'a lot' 的确切定义可能会有所不同且难以确定,所有常见的 JVM 将 JIT-compile 代码,从根本上改变性能。如果您经常这样做,请务必测量编译性能,如果您不经常这样做,则性能通常不会'没关系。关于 'microbenchmark(s)' 中 Java 的陷阱,SO 上存在 许多 个现有问题。