转换贝利&x2013;从Python到Java的PSW测试
我正在尝试将Baillie–PSW素性测试的一个实现从Python转换为Java。 我认为我做的基本上是对的,但是有一部分答案开始偏离,结果整个算法无法检测到任何素数。当算法开始使用Lucas素性测试时,就会出现这种偏差 以下是部分测试(部分测试)的原始代码: 下面是我的Java对应项:转换贝利&x2013;从Python到Java的PSW测试,java,python,bit-manipulation,primes,Java,Python,Bit Manipulation,Primes,我正在尝试将Baillie–PSW素性测试的一个实现从Python转换为Java。 我认为我做的基本上是对的,但是有一部分答案开始偏离,结果整个算法无法检测到任何素数。当算法开始使用Lucas素性测试时,就会出现这种偏差 以下是部分测试(部分测试)的原始代码: 下面是我的Java对应项: static long[] UVSubscript(long k, long n, long U, long V, long P, long Q, long D){ BitSet bitDigits =
static long[] UVSubscript(long k, long n, long U, long V, long P, long Q, long D){
BitSet bitDigits = convert(k);
long subscript = 1;
for (int i = bitDigits.length()-2; i >= 0; i--) {
U = U*V % n;
V = (powerModulus(V, 2, n) - 2*powerModulus(Q, subscript, n)) % n;
subscript *= 2;
if (bitDigits.get(i)){
if (((P * U + V) & 1) == 0){
if (((D*U + P*V) & 1) == 0){
U = (P*U + V) >> 1;
V = (D*U + P*V) >> 1;
}else{
U = (P*U + V) >> 1;
V = (D*U + P*V + n) >> 1;
}
} else if (((D * U + P * V) & 1) == 0){
U = (P*U + V + n) >> 1;
V = (D*U + P*V) >> 1;
}else{
U = (P*U + V + n) >> 1;
V = (D*U + P*V + n) >> 1;
}
subscript += 1;
U = U % n;
V = V % n;
}
}
return new long[]{U, V};
}
有人能帮我吗?如果有人感兴趣的话,给你。这是我的
PS如果有人知道Baillie–PSW素性测试的现成Java实现,我可以使用它 我能看到的一个地方是你对这一行的翻译,以及三个类似的翻译:
U, V = (P*U + V + n) >> 1, (D*U + P*V + n) >> 1
这些是Python中的并行赋值,即使用语句之前的U
旧值计算V
。但在你的翻译中:
U = (P*U + V + n) >> 1;
V = (D*U + P*V + n) >> 1;
正在使用新值U
计算V
。更好的翻译方法可能是:
long old_U = U;
U = (P*U + V + n) >> 1;
V = (D*old_U + P*V + n) >> 1;
同样,其他并行赋值也需要这样做。如果您观察到循环重复使用
p*U+V
和D*U+p*V
值,则有改进的余地。您根本不需要接受答案中提到的oldU
变量。只需在循环开始时计算这两个值,然后将它们用于条件和新U
和V
值的计算。你在两个方面都赢了:使用一个单独的值将确保分配不再是平行的,并且你可以节省一些不必要的重新计算:
if (k.testBit(i)) {
val PU_V = P * U + V
val DU_PV = D * U + P * V
if (IsEven(PU_V)) {
if (IsEven(DU_PV)) {
U = PU_V shr 1
V = DU_PV shr 1
}
else {
U = PU_V shr 1
V = (DU_PV + n) shr 1
}
}
else if (IsEven(DU_PV)) {
U = (PU_V + n) shr 1
V = DU_PV shr 1
}
else {
U = (PU_V + n) shr 1
V = (DU_PV + n) shr 1
}
subscript++
U %= n
V %= n
}
(这恰好是在Kotlin中,而不是在Java中,但这没有任何区别。)最简单的可能原因是整数溢出。如果模数大于10^9,则最有可能是这种情况。您可以尝试使用大整数来完全避免此问题。还有
(long)Math.pow(2,i)
可能不起作用(我不确定);只需使用位移位(1L
if (k.testBit(i)) {
val PU_V = P * U + V
val DU_PV = D * U + P * V
if (IsEven(PU_V)) {
if (IsEven(DU_PV)) {
U = PU_V shr 1
V = DU_PV shr 1
}
else {
U = PU_V shr 1
V = (DU_PV + n) shr 1
}
}
else if (IsEven(DU_PV)) {
U = (PU_V + n) shr 1
V = DU_PV shr 1
}
else {
U = (PU_V + n) shr 1
V = (DU_PV + n) shr 1
}
subscript++
U %= n
V %= n
}