Как я могу превратить этот код с длинным в BigInteger - PullRequest
0 голосов
/ 02 октября 2019

Это код, который получает простые числа, я сделал его настолько эффективным, насколько смог, но проблема в том, что я не могу преобразовать его в BigInteger, так как долго не может хранить столько информации;здесь код:

public class p3{
    static long perfectNumber;
    static long mersenne;

    public static void main(String[] args) {
        long p = 2;
        while (true) {
            if( p % 2 == 0&&p!=2){
                p++;
            }
            else{
                if (isPrime(p) == true) {
                    mersenne = (long) (Math.pow(2, p) - 1);
                    if (isPrime(mersenne) == true) {
                        perfectNumber = (long) Math.pow(2, (p - 1)) * mersenne;
                        System.out.println(perfectNumber);
                    }
                }
                p+=1;
            }
        }
    }
    private static boolean isPrime(long testPrime) {
        for (long i = 3; i < Math.sqrt(testPrime); i += 2) {
            if (testPrime % i == 0) {
                    return false;
            }
        }
        return true;
    }
}

1 Ответ

1 голос
/ 05 октября 2019

Я пытался использовать 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(), как считаете нужным.

...