Вернуть все простые числа меньше M

Для целого числа M. вернуть все простые числа меньше M.

Придумайте алгоритм как можно лучше. Необходимо учитывать временную и пространственную сложность.


person user658266    schedule 18.03.2011    source источник


Ответы (9)


Пара дополнительных советов по производительности:

  1. Вам нужно только проверить квадратный корень из M, поскольку каждое составное число имеет хотя бы один простой множитель, меньший или равный его квадратному корню.
  2. Вы можете кэшировать известные простые числа по мере их создания и проверять последующие числа только по числам в этом списке (вместо каждого числа ниже sqrt(M))
  3. Очевидно, вы можете пропускать четные числа (кроме 2, конечно)
person Wayne    schedule 18.03.2011
comment
3. Что ж, не стоит бросать все! Не бросайте 2 ;-) - person Curd; 18.03.2011
comment
Я считаю, что первое утверждение неверно. Например, N = 120. 113 - простое ‹N., но 113› sqrt (N). - person Juan Carlos Oropeza; 20.04.2015
comment
Я не уверен, что вы пытаетесь сказать. Конечно, могут быть (несвязанные) простые числа больше квадратного корня из N, но это не говорит нам ничего полезного. Дело в том, что каждое составное число имеет по крайней мере один простой множитель, меньший или равный его квадратному корню, и вам нужно найти только один такой множитель, чтобы доказать, что N составное (т.е. нет необходимости продолжать проверка). В этом суть первого утверждения. - person Wayne; 20.04.2015
comment
Прости. Я думаю, может быть, ваш ответ короткий и выглядит как комментарий, а не полный ответ. Когда я читаю Wiki Sieve of Eratosthenes, я понимаю ваш совет. Но поскольку ваш ответ был первым, что я прочитал, я не понял, о чем вы говорите. - person Juan Carlos Oropeza; 20.04.2015
comment
Решето Эратосфена не обязательно для понимания того математического факта, что все составные числа имеют хотя бы один простой множитель, меньший или равный их квадратному корню. Мой ответ не имеет ничего общего с Решетом Эратосфена. Я описываю метод исключения множества итераций при проверке простых чисел. Боюсь, ваши комментарии здесь не помогают. - person Wayne; 20.04.2015
comment
Вы правы, но вам нужно понимать контекст, чтобы применить этот факт. Я не говорю, что ваш ответ неверен, но я не понимал его, пока не получил контекст из другого ответа, который я просто предлагал немного улучшить ваш ответ, чтобы другие пользователи могли лучше понять, например, я путаю ваш N с OP M. Также просто осознайте, что даже когда ваш ответ был принят, ответ Эндрю получил наибольшее количество голосов, потому что он дает другим пользователям, которые ищут ответ, правильный контекст. - person Juan Carlos Oropeza; 22.04.2015

Сито Эратосфена - хорошее место для начала.

http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

person Andrew Cooper    schedule 18.03.2011
comment
Есть и другие сита, которые легко понять и не требуют O (n) пространства. Или вы просто делаете это для постоянного количества чисел снова и снова. Например. вы хотите, чтобы все простые числа были меньше 10000, а затем делайте это партиями по 100 или 1000, чтобы уменьшить использование пространства и только потом сохранить простые числа. - person HopefullyHelpful; 05.05.2016
comment
O (n) пространство - это большая сложность пространства, если N больше, может быть 2 миллиарда или больше. Лучше всего использовать Сито Аткина. - person Krish Bhanushali; 01.02.2018

обычный ответ - реализовать Сито Эратосфена, но на самом деле это всего лишь решение для поиска списка всех простых чисел, меньших N. Если вы хотите тесты простоты для конкретных чисел, для больших чисел есть лучшие варианты.

person sarnold    schedule 18.03.2011

Сито Эратосфена хорошее.

person user664982    schedule 18.03.2011

Я начинающий программист на C # (и новичок в S.O.), так что это может быть немного многословным. Тем не менее, я проверил это, и я работаю.

вот что я придумал:

for (int i = 2; i <= n; i++)
{
    while (n % i == 0)
    {
        Console.WriteLine(i.ToString());
        n /= i;
    }
}
Console.ReadLine();
person Martin Andrews    schedule 12.06.2013

π (n) подсчитывает простые числа, меньшие или равные n. Пафнутий Чебышев показал, что если

lim n → ∞ π (n) / (n / ln (n))

существует, оно равно 1. На самом деле существует множество значений, которые примерно равны π (n), как показано в таблице.

введите описание изображения здесь

Это дает правильное число простого числа для этого числового формата. Надеюсь, это будет полезно.

person Ujjwal    schedule 15.06.2015
comment
Это не отвечает на вопрос. - person ; 28.11.2018

Вы можете сделать это, используя подход динамического программирования снизу вверх, называемый Решетом Эратосфена. В основном вы создаете логический кеш всех чисел до n и помечаете каждое кратное каждого числа как not_prime. Дальнейшая оптимизация может быть достигнута путем проверки только до sqrt (n), так как любое составное число будет иметь хотя бы один делитель меньше, чем sqrt (n).

    public int countPrimes(int n) {
    if(n==0){
        return 0;
    }else{
        boolean[] isPrime=new boolean[n];
        for(int i=2;i<n;i++){
            isPrime[i]=true;
        }

        /* Using i*i<n instead of i<Math.sqrt(n)
         to avoid the exepnsive sqrt operation */
        for(int i=2;i*i<n;i++){
           if(!isPrime[i]){
               continue;
           }
            for(int j=i*i;j<n;j+=i){
                isPrime[j]=false;
            }
        }

        int counter=0;
        for(int i=2;i<n;i++){
            if(isPrime[i]){
                counter++;
            }
        }

        return counter;

    }
}
person Mad Scientist    schedule 02.04.2016

Это то, что я разработал для Seive of Eratosthenes. Конечно, были бы и лучшие реализации.

// находит количество простых чисел меньше длины

private static int findNumberOfPrimes(int length) {
    int numberOfPrimes = 1;
    if (length == 2) {
        return 1;
    }

    int[] arr = new int[length];
    //creating an array of numbers less than 'length'
    for (int i = 0; i < arr.length; i++) {
        arr[i] = i + 1;
    }
    //starting with first prime number 2, all the numbers divisible by 2(and upcoming) is replaced with -1
    for (int i = 2; i < arr.length && arr[i] != -1; i++) {

        for (int j = i; j < arr.length; j++) {
            if (arr[j] % arr[i] == 0) {
                arr[j] = -1;
                numberOfPrimes += 1;
            }
        }

    }
    return numberOfPrimes;
}
person Vikash    schedule 02.07.2016

Сито Аткина также является лучшим алгоритмом для реализации в этом случае, и для него требуется всего O (N) операций и O (N) пространства. Подробное описание алгоритм и псевдокод.

person Krish Bhanushali    schedule 31.01.2018