Я пытался использовать BigInteger, но код не работает, так как я не могу использовать экспоненты BigInteger с pow
Вам не нужно. Показатели степени не должны быть почти такими же большими, как простые числа Мерсенна и совершенные числа. Они могут иметь свой собственный независимый isPrime()
тест. На самом деле они должны быть int
вместо long
, чтобы удовлетворить BigInteger.pow()
.
Ниже приведено то, о чем вы просили, но, возможно, не то, что вы хотите. Я сомневаюсь, что вы получите более одного дополнительного идеального числа помимо исходного кода из-за временных ограничений, поэтому @WJS подталкивает вас в другом направлении.
import java.math.BigInteger;
public class p3 {
static BigInteger TWO = new BigInteger("2");
static BigInteger THREE = new BigInteger("3");
public static void main(String[] args) {
int p = 2;
while (true) {
if (isPrime(p)) {
BigInteger mersenne = TWO.pow(p).subtract(BigInteger.ONE);
if (isPrime(mersenne)) {
System.out.println(TWO.pow(p - 1).multiply(mersenne));
}
}
p += (p == 2) ? 1 : 2;
}
}
private static boolean isPrime(BigInteger number) {
if (number.mod(TWO).equals(BigInteger.ZERO)) {
return number.equals(TWO);
}
for (BigInteger i = THREE; number.compareTo(i.multiply(i)) >= 0; i = i.add(TWO)) {
if (number.mod(i).equals(BigInteger.ZERO)) {
return false;
}
}
return true;
}
private static boolean isPrime(int number) {
if (number % 2 == 0) {
return number == 2;
}
for (int i = 3; number >= i * i; i += 2) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
ВЫХОД
> java p3
6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
2658455991569831744654692615953842176
Ваш исходный код выводит 0 вместо последнего (37-значного) числа выше. Так что непосредственная проблема в том, что long
не может содержать достаточно информации. Но после этого вы просто не сможете достаточно быстро вычислить с помощью вышеуказанного алгоритма.
Если мы сделаем что-то простое с моим кодом, например, заменим эту строку:
if (isPrime(mersenne)) {
с:
if (mersenne.isProbablePrime(10)) {
Код будет выплевывать первые 20 совершенных чисел, прежде чем замедлить до сканирования. Настройте определенность аргумент isProbablePrime()
, как считаете нужным.