Обработка больших входов для моего теста java primality? [Дубликат]

Вы можете использовать эту пользовательскую библиотеку (написанную с помощью Promise) для выполнения удаленного вызова.

function $http(apiConfig) {
    return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                // Performs the function "resolve" when this.status is equal to 2xx.
                // Your logic here.
                resolve(this.response);
            }
            else {
                // Performs the function "reject" when this.status is different than 2xx.
                reject(this.statusText);
            }
        };
        client.onerror = function () {
            reject(this.statusText);
        };
    });
}

Пример простого использования:

$http({
    method: 'get',
    url: 'google.com'
}).then(function(response) {
    console.log(response);
}, function(error) {
    console.log(error)
});
45
задан PeeHaa 3 November 2013 в 20:07
поделиться

13 ответов

Вот еще один способ:

boolean isPrime(long n) {
    if(n < 2) return false;
    if(n == 2 || n == 3) return true;
    if(n%2 == 0 || n%3 == 0) return false;
    long sqrtN = (long)Math.sqrt(n)+1;
    for(long i = 6L; i <= sqrtN; i += 6) {
        if(n%(i-1) == 0 || n%(i+1) == 0) return false;
    }
    return true;
}

и BigInteger's isProbablePrime(...) допустим для всех 32-битных int.

EDIT

Обратите внимание, что isProbablePrime(certainty) не всегда дает правильный ответ. Когда определенность находится на нижней стороне, она создает ложные срабатывания, как указано в комментариях @ dimo414.

К сожалению, я не смог найти источник, который утверждал, что isProbablePrime(certainty) действителен для всех (32-разрядный ) int (с достаточной уверенностью!).

Итак, я выполнил пару тестов. Я создал BitSet размера Integer.MAX_VALUE/2, представляющего все неравные числа, и использовал первичное сито, чтобы найти все простые числа в диапазоне 1..Integer.MAX_VALUE. Затем я зациклился от i=1..Integer.MAX_VALUE, чтобы проверить, что каждый new BigInteger(String.valueOf(i)).isProbablePrime(certainty) == isPrime(i).

Для достоверности 5 и 10, isProbablePrime(...) произвели ложные срабатывания вдоль линии. Но с isProbablePrime(15) тест не сработал.

Вот моя тестовая установка:

import java.math.BigInteger;
import java.util.BitSet;

public class Main {

    static BitSet primes;

    static boolean isPrime(int p) {
        return p > 0 && (p == 2 || (p%2 != 0 && primes.get(p/2)));
    }

    static void generatePrimesUpTo(int n) {
        primes = new BitSet(n/2);

        for(int i = 0; i < primes.size(); i++) {
            primes.set(i, true);
        }

        primes.set(0, false);
        int stop = (int)Math.sqrt(n) + 1;
        int percentageDone = 0, previousPercentageDone = 0;
        System.out.println("generating primes...");
        long start = System.currentTimeMillis();

        for(int i = 0; i <= stop; i++) {
            previousPercentageDone = percentageDone;
            percentageDone = (int)((i + 1.0) / (stop / 100.0));

            if(percentageDone <= 100 && percentageDone != previousPercentageDone) {
                System.out.println(percentageDone + "%");
            }

            if(primes.get(i)) {
                int number = (i * 2) + 1;

                for(int p = number * 2; p < n; p += number) {
                    if(p < 0) break; // overflow
                    if(p%2 == 0) continue;
                    primes.set(p/2, false);
                }
            }
        }
        long elapsed = System.currentTimeMillis() - start;
        System.out.println("finished generating primes ~" + (elapsed/1000) + " seconds");
    }

    private static void test(final int certainty, final int n) {
        int percentageDone = 0, previousPercentageDone = 0;
        long start = System.currentTimeMillis();
        System.out.println("testing isProbablePrime(" + certainty + ") from 1 to " + n);
        for(int i = 1; i < n; i++) {
            previousPercentageDone = percentageDone;
            percentageDone = (int)((i + 1.0) / (n / 100.0));
            if(percentageDone <= 100 && percentageDone != previousPercentageDone) {
                System.out.println(percentageDone + "%");
            }
            BigInteger bigInt = new BigInteger(String.valueOf(i));
            boolean bigIntSays = bigInt.isProbablePrime(certainty);
            if(isPrime(i) != bigIntSays) {
                System.out.println("ERROR: isProbablePrime(" + certainty + ") returns "
                    + bigIntSays + " for i=" + i + " while it " + (isPrime(i) ? "is" : "isn't" ) +
                    " a prime");
                return;
            }
        }
        long elapsed = System.currentTimeMillis() - start;
        System.out.println("finished testing in ~" + ((elapsed/1000)/60) +
                " minutes, no false positive or false negative found for isProbablePrime(" + certainty + ")");
    }

    public static void main(String[] args) {
        int certainty = Integer.parseInt(args[0]);
        int n = Integer.MAX_VALUE;
        generatePrimesUpTo(n);
        test(certainty, n);
    }
}

, которую я выполнил:

java -Xmx1024m -cp . Main 15

из простых чисел на моей машине было ~ 30 секунд. И фактическое испытание всех i в 1..Integer.MAX_VALUE заняло около 2 часов и 15 минут.

67
ответ дан Bart Kiers 5 September 2018 в 10:26
поделиться

Ваш алгоритм будет хорошо работать для достаточно малых чисел. Для больших чисел следует использовать передовые алгоритмы (например, на эллиптических кривых). Другая идея будет заключаться в использовании некоторых тестов «псевдопробы». Они будут быстро проверять, что число является простым, но они не на 100% точны. Тем не менее, они могут помочь вам исключить некоторые цифры быстрее, чем с вашим алгоритмом.

Наконец, хотя компилятор, вероятно, оптимизирует это для вас, вы должны написать:

int max =  (int) (Math.sqrt(n) + 1);
for (int i = 3; i <= max; i = i + 2) {
}
4
ответ дан Andrew Clear 5 September 2018 в 10:26
поделиться

Я думаю, что этот метод лучше. по крайней мере для меня -

    public static boolean isPrime(int num)
    {
        for (int i = 2; i<= num/i; i++)
        {
            if (num % i == 0)
            {
                return false;
            }
        }
        return num > 1;
    }
3
ответ дан Ariful Islam 5 September 2018 в 10:26
поделиться

Есть, конечно, сотни тестов примитивности, все из которых имеют различные преимущества и недостатки, основанные на размере числа, специальных формах, размере фактора и т. д.

Однако в java я нахожу наиболее полезным это:

BigInteger.valueOf(long/int num).isProbablePrime(int certainty);

Его уже реализовано и довольно быстро (я нахожу, что для матрицы 1000x1000, заполненной длинными 0-2 ^ 64 и уверенностью 15, требуется ~ 6 секунд) и, вероятно, лучше оптимизирован, чем все, что могли бы предложить смертные.

Он использует версию теста Baillie-PSW primality , которая не знает контрпримеры. (хотя он может использовать немного более слабую версию теста, что иногда может ошибиться).

2
ответ дан Ash Pera 5 September 2018 в 10:26
поделиться

В зависимости от длины числа, которое необходимо проверить, вы можете предварительно скопировать список простых чисел для небольших значений (n & lt; 10 ^ 6), который используется первым, если запрашиваемый номер находится в этом диапазоне. Это, конечно, самый быстрый путь. Как упоминалось в других ответах, сито Эратосфена является предпочтительным способом генерации такого предварительно вычисленного списка.

Если ваши цифры больше этого, вы можете использовать тест прочности Рабина , Тест на первичность Рабина

3
ответ дан Aurril 5 September 2018 в 10:26
поделиться

Быстрый тест из-за Jaeschke (1993) является детерминированной версией теста Миллера-Рабина, который не имеет ложных срабатываний ниже 4,759,123,141 и поэтому может быть применен к Java int s.

// Given a positive number n, find the largest number m such
// that 2^m divides n.
private static int val2(int n) {
  int m = 0;
  if ((n&0xffff) == 0) {
    n >>= 16;
    m += 16;
  }
  if ((n&0xff) == 0) {
    n >>= 8;
    m += 8;
  }
  if ((n&0xf) == 0) {
    n >>= 4;
    m += 4;
  }
  if ((n&0x3) == 0) {
    n >>= 2;
    m += 2;
  }
  if (n > 1) {
    m++
  }
  return m;
}

// For convenience, handle modular exponentiation via BigInteger.
private static int modPow(int base, int exponent, int m) {
  BigInteger bigB = BigInteger.valueOf(base);
  BigInteger bigE = BigInteger.valueOf(exponent);
  BigInteger bigM = BigInteger.valueOf(m);
  BigInteger bigR = bigB.modPow(bigE, bigM);
  return bigR.intValue();
}

// Basic implementation.
private static boolean isStrongProbablePrime(int n, int base) {
  int s = val2(n-1);
  int d = modPow(b, n>>s, n);
  if (d == 1) {
    return true;
  }
  for (int i=1; i < s; i++) {
    if (d+1 == n) {
      return true;
    }
    d = d*d % n;
  }
  return d+1 == n;
}

public static boolean isPrime(int n) {
  if ((n&1) == 0) {
    return n == 2;
  }
  if (n < 9) {
    return n > 1;
  }

  return isStrongProbablePrime(n, 2) && isStrongProbablePrime(n, 7) && isStrongProbablePrime(n, 61);
}

Это не работает для переменных long, но другой тест: тест BPSW не имеет контрпримеров до 2 ^ 64. Это в основном состоит из 2-сильного вероятного простого теста, такого как выше, за которым следует сильный тест Lucas, который немного сложнее, но не принципиально отличается.

Оба этих теста намного быстрее, чем любое пробное деление .

3
ответ дан Charles 5 September 2018 в 10:26
поделиться

Я оптимизировал пробное подразделение здесь: он возвращает логическое значение. Также необходимы методы, отличные от isPrime (n).

    static boolean[] smlprime = {false, false, true, true, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false};

public static boolean isPrime(long n) { //optimised
    if (n < 2) {
        return false;
    }
    if (n < smlprime.length) //less than smlprime.length do not need to be checked
    {
        return smlprime[(int) n]; //lol already checked
    }

    long[] dgt = longDigits(n);
    long ones = dgt[dgt.length - 1];
    if (ones % 2 == 0) {
        return false;
    }
    if (ones == 0 || ones == 5) {
        return false;
    }
    if (digitadd(n) % 3 == 0) {
        return false;
    }
    if (n % 7 == 0) {
        return false;
    }
    if (Square(n)) {
        return false;
    }
    long hf = (long) Math.sqrt(n);
    for (long j = 11; j < hf; j = nextProbablePrime(j)) {
        //System.out.prlongln(Math.sqrt(i));
        if (n % j == 0) {
            return false;
        }
        //System.out.prlongln("res"+res);
    }
    return true;
}

public static long nextProbablePrime(long n) {
    for (long i = n;; i++) {
        if (i % 2 != 0 && i % 3 != 0 && i % 7 != 0) {
            return i;
        }
    }
}

public static boolean Square(long n) {
    long root = (long) Math.sqrt(n);
    return root * root == n;
}

public static long[] longDigits(long n) {
    String[] a = Long.toString(n).split("(?!^)");
    long[] out = new long[a.length];
    for (int i = 0; i < a.length; i++) {
        out[i] = Long.parseLong(a[i]);
    }
    return out;
}

public static long digitadd(long n) {
    long[] dgts = longDigits(n);
    long ans = 0;
    for (long i : dgts) {
        ans += i;
    }
    return ans;
}
1
ответ дан HiBrian 5 September 2018 в 10:26
поделиться
10
ответ дан Joe 5 September 2018 в 10:26
поделиться

То, что вы написали, - это то, что делают большинство обычных программистов и которое должно быть достаточным в большинстве случаев.

Однако, если вы после «наилучшего научного алгоритма», существует множество вариантов (с различными уровнями (g0) http://en.wikipedia.org/wiki/Prime_number .

Например, если у вас есть 70-значный номер, физические ограничения JVM могут помешать вашему коду в этом случае вы можете использовать «Сита» и т. д.

Опять же, как я уже сказал, если это был вопрос программирования или общий вопрос использования в программном обеспечении, ваш код должен быть идеальным:)

3
ответ дан Kannan Ekanath 5 September 2018 в 10:26
поделиться

Эффективность алгоритма: O (n ^ (1/2)) Алгоритм

Примечание. В этом примере кода ниже приведены счетные переменные и вызовы функции печати для печати результатов:

import java.util.*;

class Primality{
    private static void printStats(int count, int n, boolean isPrime) {

        System.err.println( "Performed " + count + " checks, determined " + n
        + ( (isPrime) ? " is PRIME." : " is NOT PRIME." ) );
    }
    /**
    *   Improved O( n^(1/2)) ) Algorithm
    *    Checks if n is divisible by 2 or any odd number from 3 to sqrt(n).
    *    The only way to improve on this is to check if n is divisible by 
    *   all KNOWN PRIMES from 2 to sqrt(n).
    *
    *   @param n An integer to be checked for primality.
    *   @return true if n is prime, false if n is not prime.
    **/
    public static boolean primeBest(int n){
        int count = 0;
        // check lower boundaries on primality
        if( n == 2 ){ 
            printStats(++count, n, true);
            return true;
        } // 1 is not prime, even numbers > 2 are not prime
        else if( n == 1 || (n & 1) == 0){
            printStats(++count, n, false);
            return false;
        }

        double sqrtN = Math.sqrt(n);
        // Check for primality using odd numbers from 3 to sqrt(n)
        for(int i = 3; i <= sqrtN; i += 2){
            count++;
            // n is not prime if it is evenly divisible by some 'i' in this range
            if( n % i == 0 ){ 
                printStats(++count, n, false);
                return false;
            }
        }
        // n is prime
        printStats(++count, n, true);
        return true;
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        while(scan.hasNext()) {
            int n = scan.nextInt();
            primeBest(n);
            System.out.println();
        }
        scan.close();
    }
}

Когда введено простое число 2147483647, он производит следующий вывод:

Выполнено 23170 проверок, определено 2147483647 является PRIME.

1
ответ дан Radiodef 5 September 2018 в 10:26
поделиться

Если вы просто пытаетесь найти, является ли число простым или нет, это достаточно хорошо, но если вы пытаетесь найти все простые числа от 0 до na, лучшим вариантом будет сито Eratosthenes

Но это будет зависеть от ограничений java на размерах массива и т. д.

4
ответ дан saugata 5 September 2018 в 10:26
поделиться

Это самый элегантный способ:

public static boolean isPrime(int n) {
    return !new String(new char[n]).matches(".?|(..+?)\\1+");
}

Java 1.4+. Импорт не требуется.

Так коротка. Так красиво.

42
ответ дан user102008 5 September 2018 в 10:26
поделиться

Взгляните на тест присадки AKS (и его различные оптимизации). Это детерминированный тест примитивности, который выполняется в полиномиальное время.

Здесь имеется реализация алгоритма в Java из Университета Тюбингена (Германия)

12
ответ дан zx485 5 September 2018 в 10:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: