Самый эффективный код для первых 10000 простых чисел?

Я хочу вывести первые 10000 простых чисел. Может 9X_prime-number ли кто-нибудь дать мне наиболее эффективный 9X_performance код для этого? Уточнения:

  1. Неважно, неэффективен ли ваш код для n >10000.
  2. Размер кода не имеет значения.
  3. Вы не можете просто жестко закодировать значения каким-либо образом.

65
2

  • Имейте в виду, что найти первые 10000 простых чисел - относительно небольшая задача. Вы можете заметить разн ...
20
Общее количество ответов: 20

Ответ #1

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

The Sieve of Atkin, вероятно, то, что вы ищете, его верхняя 9X_performance граница времени работы составляет O(N/log 9X_algorithm-design log N).

Если вы запускаете только числа, на 9X_perfomance 1 больше и на 1 меньше, чем числа, кратные 9X_algorithm 6, это может быть еще быстрее, поскольку 9X_algorithms все простые числа выше 3 на 1 отличаются 9X_performance от некоторого числа, кратного шести. Resource for my statement

50
4

  • Поскольку это помечено как 'answer': -1 для разговора об асимптотике, когда OP хочет эффективности для небольшого фиксированного n, равного ...

Ответ #2

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Я рекомендую сито, либо Sieve of Eratosthenes, либо Sieve of Atkin.

Решето или 9X_tuning Эратосфен, вероятно, самый интуитивный метод 9X_primes поиска списка простых чисел. В основном 9X_faster вы:

  1. Запишите список чисел от 2 до любого желаемого предела, скажем, 1000.
  2. Возьмите первое незачеркнутое число (для первой итерации это 2) и вычеркните из списка все числа, кратные этому числу.
  3. Повторяйте шаг 2, пока не дойдете до конца списка. Все числа, которые не вычеркнуты, являются простыми.

Очевидно, что существует довольно много 9X_perfomance оптимизаций, которые могут ускорить работу 9X_efficiency этого алгоритма, но это основная идея.

Решето 9X_slow Аткина использует аналогичный подход, но, к 9X_speed сожалению, я недостаточно знаю о нем, чтобы 9X_slow объяснить его вам. Но я знаю, что алгоритм, который 9X_fast я привел, занимает 8 секунд, чтобы вычислить 9X_speed все простые числа до 1000000000 на древнем 9X_perfomance Pentium II-350

Сито Эратосфена Исходный код: http://web.archive.org/web/20140705111241/http://primes.utm.edu/links/programs/sieves/Eratosthenes/C_source_code/

Решето 9X_prime-number Аткина Исходный код: http://cr.yp.to/primegen.html

39
0

Ответ #3

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Это не строго противоречит ограничениям 9X_android-performance жесткого кодирования, но очень близко. Почему 9X_faster бы вместо этого программно не загрузить 9X_performance этот список и не распечатать его?

http://primes.utm.edu/lists/small/10000.txt

20
3

  • лол @krog. Зачем вам каждый раз настраивать сетевое соединение и всякую эту чепуху для DL статического файла? конечно, вы бы предварительно загрузили его, черт возьми, даж ...

Ответ #4

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

В Haskell мы можем почти дословно записать 9X_efficiency математическое определение решета Эратосфена: «простые числа - это натуральные числа больше 1 без составных чисел, где составные числа находятся путем перечисления кратных каждому простому числу ":

import Data.List.Ordered (minus, union) primes = 2 : minus [3..] (foldr (\p r -> p*p : union [p*p+p, p*p+2*p..] r) [] primes) 

primes !! 10000 почти 9X_efficiency мгновенно.

Ссылки:

  • Sieve of Eratosthenes
  • Richard Bird's sieve (see pp. 10,11)
  • minus, union

Приведенный выше код легко настроить для работы только с коэффициентами, primes = 2 : 3 : minus [5,7..] (foldr (\p r -> p*p : union [p*p+2*p, p*p+4*p..] r) [] (tail primes)). Сложность времени значительно улучшена (почти до log фактора выше оптимального) за счет сворачивания в древовидную структуру, а сложность пространства на drastically improved на multistage primes production в

primes = 2 : _Y ( (3:) . sieve 5 . _U . map (\p -> [p*p, p*p+2*p..]) ) where _Y g = g (_Y g) -- non-sharing fixpoint combinator _U ((x:xs):t) = x : (union xs . _U . pairs) t -- ~= nub.sort.concat pairs (xs:ys:t) = union xs ys : pairs t sieve k s@(x:xs) | k < x = k : sieve (k+2) s -- ~= [k,k+2..]\\s, | otherwise = sieve (k+2) xs -- when s⊂[k,k+2..] 

(В Haskell круглые скобки используются для группировки, вызов функции обозначается просто сопоставлением, (:) является оператором cons для списков и (.) - оператор функциональной композиции: (f . g) x = (\y -> f (g y)) x = f (g x)).

15
2

  • Недавно я придумал [модифицированную версию Sieve of Sundaram] (http://stackoverflow.com/a/41434702/4543207), которая кажется вдвое более производительной по сравнению с Sieve of Eratosthenes. Я р ...

Ответ #5

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

GateKiller, как насчет добавления break к этому if в цикле 9X_efficiency foreach? Это ускорит работу намного, потому что, если 9X_algorithm-design 6 делится на 2, вам не нужно проверять 3 9X_algorithm-design и 5. (Я бы все равно проголосовал за ваше 9X_efficiency решение, если бы у меня было достаточно 9X_faster репутации :-) ...)

ArrayList primeNumbers = new ArrayList(); for(int i = 2; primeNumbers.Count < 10000; i++) { bool divisible = false; foreach(int number in primeNumbers) { if(i % number == 0) { divisible = true; break; } } if(divisible == false) { primeNumbers.Add(i); Console.Write(i + " "); } } 

13
1

  • Вы все еще можете значительно ускорить это, также нарушив if number> sqrt (i).<p><s ...

Ответ #6

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

@Matt: log(log(10000)) равно ~2

Из статьи 9X_speed в Википедии (которую вы цитировали) Sieve of Atkin:

Это 9X_speed решето вычисляет простые числа до N используя 9X_algorithm O(N/log log N) операции с только N1/2+o(1) бит памяти. То есть немного 9X_faster лучше, чем сито Эратосфен, который использует 9X_efficiency O(N) операций и O(N1/2(log log N)/log N) бит 9X_algorithm-design памяти (A.O.L. Atkin, D.J. Bernstein, 2004). Эти асимптотические вычислительные 9X_speed сложности включают простые оптимизации, такие 9X_algorithm-design как колесо факторизация и разбиение вычисления 9X_algorithms на меньшие блоки.

Учитывая асимптотическую 9X_fast сложность вычислений вдоль O(N) (для Эратосфена) и 9X_algorithm O(N/log(log(N))) (для Аткина), мы не можем сказать (для 9X_faster малых N=10_000), какой алгоритм, если он будет реализован, будет 9X_perfomance быстрее.

Ахим Фламменкамп написал в The Sieve of Eratosthenes:

процитировано:

@num1

Для 9X_slow интервалов больше примерно 10 ^ 9, конечно 9X_algorithm для тех > 10^10, сито Эратосфен уступает Решето 9X_tuning Аткинса и Бернштейна, которое использует 9X_primes неприводимый двоичный квадратичный формы. См. их 9X_algorithm статью для фона информацию, а также пункт 9X_performance 5 Доктор философии В. Голуэя. Тезис.

Поэтому 9X_prime-number для 10_000 Решето Эратосфена может быть быстрее, чем 9X_faster Решето Аткина.

Для ответа OP используйте 9X_algorithm-design код prime_sieve.c (цитируется num1)

11
0

Ответ #7

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Используя GMP, можно было бы написать следующее:

#include #include int main() { mpz_t prime; mpz_init(prime); mpz_set_ui(prime, 1); int i; char* num = malloc(4000); for(i=0; i<10000; i++) { mpz_nextprime(prime, prime); printf("%s, ", mpz_get_str(NULL,10,prime)); } } 

На 9X_algorithms моем Macbook Pro с частотой 2,33 ГГц он 9X_slow выполняется следующим образом:

time ./a.out > /dev/null real 0m0.033s user 0m0.029s sys 0m0.003s 

Вычисление 9X_prime-number 1 000 000 простых чисел на одном ноутбуке:

time ./a.out > /dev/null real 0m14.824s user 0m14.606s sys 0m0.086s 

GMP 9X_android-performance очень оптимизирован для такого рода вещей. Если 9X_performance-tuning вы действительно не хотите понимать алгоритмы, написав 9X_efficiency свои собственные, вам рекомендуется использовать 9X_algorithm libGMP под C.

9
1

  • mpz_nextprime вычисляет простые числа по одному, а не все сразу с помощью сита<p><s ...

Ответ #8

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Совершенно неэффективно, но вы можете использовать 9X_tuning регулярное выражение для проверки простых 9X_speed чисел.

/^1?$|^(11+?)\1+$/ 

Это проверяет, является ли для строки, состоящей 9X_perfomance из k «1» s, k не простым числом (т. е. состоит ли строка из 9X_primes одного «1» или любого количества «1» s, которое 9X_android-performance может быть выражено как n-арное произведение).

7
0

Ответ #9

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Я адаптировал код, найденный на CodeProject, чтобы 9X_primes создать следующее:

ArrayList primeNumbers = new ArrayList(); for(int i = 2; primeNumbers.Count < 10000; i++) { bool divisible = false; foreach(int number in primeNumbers) { if(i % number == 0) { divisible = true; } } if(divisible == false) { primeNumbers.Add(i); Console.Write(i + " "); } } 

Проверка этого на моем 9X_fast сервере ASP.NET заняла около 1 минуты.

5
2

  • Вы можете ускорить это, если выйдете из цикла ...

Ответ #10

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Sieve of Eratosthenes — это путь из-за его простоты и скорости. Моя 9X_perfomance реализация на C

#include #include #include #include int main(void) { unsigned int lim, i, j; printf("Find primes upto: "); scanf("%d", &lim); lim += 1; bool *primes = calloc(lim, sizeof(bool)); unsigned int sqrtlim = sqrt(lim); for (i = 2; i <= sqrtlim; i++) if (!primes[i]) for (j = i * i; j < lim; j += i) primes[j] = true; printf("\nListing prime numbers between 2 and %d:\n\n", lim - 1); for (i = 2; i < lim; i++) if (!primes[i]) printf("%d\n", i); return 0; } 

CPU Time для поиска простых 9X_slow чисел (на Pentium Dual Core E2140 1,6 ГГц, с 9X_algorithm использованием одного ядра)

~ 4 с для lim 9X_algorithms = 100 000 000

4
1

  • это не отвечает на вопрос: он попросил первые N простых чисел, а не вс ...

Ответ #11

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Вот сито Эратосфена, которое я написал в 9X_primes PowerShell несколько дней назад. У него 9X_algorithms есть параметр для определения количества 9X_algorithm-design простых чисел, которые должны быть возвращены.

# # generate a list of primes up to a specific target using a sieve of eratosthenes # function getPrimes { #sieve of eratosthenes, http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes param ($target,$count = 0) $sieveBound = [math]::ceiling(( $target - 1 ) / 2) #not storing evens so count is lower than $target $sieve = @($false) * $sieveBound $crossLimit = [math]::ceiling(( [math]::sqrt($target) - 1 ) / 2) for ($i = 1; $i -le $crossLimit; $i ++) { if ($sieve[$i] -eq $false) { $prime = 2 * $i + 1 write-debug "Found: $prime" for ($x = 2 * $i * ( $i + 1 ); $x -lt $sieveBound; $x += 2 * $i + 1) { $sieve[$x] = $true } } } $primes = @(2) for ($i = 1; $i -le $sieveBound; $i ++) { if($count -gt 0 -and $primes.length -ge $count) { break; } if($sieve[$i] -eq $false) { $prime = 2 * $i + 1 write-debug "Output: $prime" $primes += $prime } } return $primes } 

3
0

Ответ #12

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Адаптация и развитие GateKiller, вот последняя версия, которую 9X_algorithms я использовал.

 public IEnumerable PrimeNumbers(long number) { List primes = new List(); for (int i = 2; primes.Count < number; i++) { bool divisible = false; foreach (int num in primes) { if (i % num == 0) divisible = true; if (num > Math.Sqrt(i)) break; } if (divisible == false) primes.Add(i); } return primes; } 

Это в основном то же самое, но 9X_algorithm я добавил предложение «перерыв на Sqrt» и 9X_prime-number изменил некоторые из переменных, чтобы он 9X_performance лучше подходил для меня. (Я работал над 9X_tuning Эйлером, и мне нужно было 10001-е простое 9X_performance-tuning число)

2
0

Ответ #13

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Сито кажется неправильным ответом. Сито 9X_algorithm-design дает вам простые числа от до числа N, а не 9X_tuning первых N простых чисел. Запустите @Imran или @Andrew 9X_android-performance Szeto, и вы получите простые числа до N.

Сито 9X_algorithm-design все еще можно использовать, если вы продолжаете 9X_faster пробовать сита для все больших чисел, пока 9X_performance-tuning не достигнете определенного размера вашего 9X_android-performance набора результатов, и использовать некоторое 9X_algorithms кеширование уже полученных чисел, но я считаю, что 9X_performance-tuning это все равно будет не быстрее, чем решение 9X_performance-tuning как у @ Pat's.

2
1

  • Требуемый верхний предел легко оценить, с некоторым запасом, как `m = n (log n + log (log n))` для `n> ...

Ответ #14

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

deque sieve algorithm mentioned by BenGoldberg заслуживает более внимательного изучения 9X_perfomance не только потому, что он очень элегантен, но 9X_algorithms и потому, что иногда он может быть полезен 9X_tuning на практике (в отличие от решета Аткина, которое 9X_fast является чисто академическим упражнением).

Основная 9X_prime-number идея алгоритма deque sieve заключается в 9X_algorithm использовании небольшого скользящего сита, которое 9X_fast достаточно велико, чтобы содержать хотя 9X_faster бы одно отдельное кратное для каждого из 9X_algorithm текущих «активных» простых множителей, то 9X_android-performance есть тех простых чисел, квадрат которых 9X_algorithms не превышает наименьшее число, представленное 9X_efficiency в настоящее время движущимся ситом. Еще 9X_algorithm одно отличие SoE заключается в том, что 9X_tuning сито deque сохраняет фактические факторы 9X_faster в слотах композитов, а не логические значения.

Алгоритм 9X_efficiency увеличивает размер окна сита по мере необходимости, что 9X_slow приводит к довольно равномерной производительности 9X_performance-tuning в широком диапазоне до тех пор, пока сито 9X_algorithm-design не начнет заметно превышать емкость кэша 9X_algorithm L1 ЦП. Последнее простое число, которое 9X_android-performance полностью соответствует, составляет 25 237 9X_efficiency 523 (1 579 791-е простое число), что дает 9X_algorithm приблизительную цифру для разумного рабочего 9X_algorithm диапазона алгоритма.

Алгоритм довольно прост 9X_fast и надежен, и он имеет даже производительность 9X_faster в гораздо более широком диапазоне, чем несегментированное 9X_fast Сито Эратосфена. Последний работает намного 9X_algorithm быстрее, если его сито полностью помещается 9X_android-performance в кеш, то есть до 2 ^ 16 для сита только 9X_fast для случайных чисел с булевыми значениями. Затем 9X_tuning его производительность падает все больше 9X_algorithms и больше, хотя он всегда остается значительно 9X_efficiency быстрее, чем deque, несмотря на недостатки 9X_performance (по крайней мере, в компилируемых языках, таких 9X_performance как C / C++, Pascal или Java / C#).

Вот визуализация 9X_speed алгоритма deque sieve на C#, потому что 9X_algorithms я считаю этот язык - несмотря на его многочисленные 9X_slow недостатки - гораздо более практичным для 9X_fast создания прототипов алгоритмов и экспериментов, чем 9X_android-performance в высшей степени громоздкий и педантичный 9X_speed C++. (Примечание: я использую бесплатный LINQPad, который позволяет погрузиться прямо в него, без всякого беспорядка с настройкой проектов, make-файлов, каталогов и т. д., и дает мне ту же степень интерактивности, что и приглашение python).

В C# нет явного типа двухсторонней 9X_android-performance очереди, но простой List работает достаточно 9X_slow хорошо для демонстрации алгоритма.

Примечание: в 9X_algorithm этой версии не используется двухсторонняя 9X_speed очередь для простых чисел, потому что просто 9X_perfomance не имеет смысла извлекать sqrt (n) из n 9X_faster простых чисел. Что хорошего в том, чтобы 9X_android-performance удалить 100 простых чисел и оставить 9900? По 9X_android-performance крайней мере, так все простые числа собраны 9X_perfomance в аккуратный вектор, готовый для дальнейшей 9X_efficiency обработки.

static List deque_sieve (int n = 10000) { Trace.Assert(n >= 3); var primes = new List() { 2, 3 }; var sieve = new List() { 0, 0, 0 }; for (int sieve_base = 5, current_prime_index = 1, current_prime_squared = 9; ; ) { int base_factor = sieve[0]; if (base_factor != 0) { // the sieve base has a non-trivial factor - put that factor back into circulation mark_next_unmarked_multiple(sieve, base_factor); } else if (sieve_base < current_prime_squared) // no non-trivial factor -> found a non-composite { primes.Add(sieve_base); if (primes.Count == n) return primes; } else // sieve_base == current_prime_squared { // bring the current prime into circulation by injecting it into the sieve ... mark_next_unmarked_multiple(sieve, primes[current_prime_index]); // ... and elect a new current prime current_prime_squared = square(primes[++current_prime_index]); } // slide the sieve one step forward sieve.RemoveAt(0); sieve_base += 2; } } 

Вот две вспомогательные функции:

static void mark_next_unmarked_multiple (List sieve, int prime) { int i = prime, e = sieve.Count; while (i < e && sieve[i] != 0) i += prime; for ( ; e <= i; ++e) // no List<>.Resize()... sieve.Add(0); sieve[i] = prime; } static int square (int n) { return n * n; } 

Вероятно, самый 9X_tuning простой способ понять алгоритм - представить 9X_algorithms его как специальное сегментированное сито 9X_speed Эратосфена с размером сегмента 1, сопровождаемое 9X_prime-number областью переполнения, где простые числа 9X_algorithm-design останавливаются, когда они стреляют через 9X_faster конец сегмента. За исключением того, что 9X_speed единственная ячейка сегмента (также известная 9X_slow как sieve[0]) уже была просеяна, когда мы дошли 9X_slow до нее, потому что она переехала, когда 9X_performance-tuning была частью области переполнения.

Число, представленное 9X_efficiency sieve[0], содержится в sieve_base, хотя sieve_front или window_base также могут 9X_algorithm быть хорошими именами, позволяющими проводить 9X_fast параллели с кодом Бена или реализациями 9X_perfomance сегментированных / оконных решет. / p>

Если 9X_algorithms sieve[0] содержит ненулевое значение, то это значение 9X_performance является множителем sieve_base, который, таким образом, может 9X_perfomance быть распознан как составной. Поскольку 9X_speed ячейка 0 кратна этому коэффициенту, легко 9X_prime-number вычислить ее следующий переход, который 9X_algorithm-design просто равен 0 плюс этот коэффициент. Если 9X_primes эта ячейка уже занята другим фактором, мы 9X_faster просто добавляем фактор снова, и так до 9X_primes тех пор, пока не найдем множитель, в котором 9X_performance в настоящее время не припаркован никакой 9X_algorithm другой фактор (при необходимости расширяя 9X_algorithms решето). Это также означает, что нет необходимости 9X_android-performance хранить текущие рабочие смещения различных 9X_primes простых чисел от одного сегмента к другому, как 9X_performance-tuning в обычном сегментированном сите. Всякий 9X_android-performance раз, когда мы находим коэффициент в sieve[0], его 9X_performance-tuning текущее рабочее смещение равно 0.

Текущее 9X_android-performance простое число вступает в игру следующим 9X_algorithms образом. Простое число может стать текущим 9X_performance только после его собственного появления 9X_perfomance в потоке (т. Е. Когда оно было обнаружено 9X_primes как простое число, потому что оно не отмечено 9X_primes коэффициентом), и оно будет оставаться текущим 9X_fast до того момента, когда sieve[0] достигнет своего 9X_algorithm-design квадрата. Все младшие кратные этого простого 9X_performance-tuning числа должны были быть удалены из-за активности 9X_android-performance меньших простых чисел, как и в обычной SoE. Но 9X_prime-number ни одно из меньших простых чисел не может 9X_slow выйти за пределы квадрата, поскольку единственный 9X_perfomance фактор квадрата - это само простое число, и 9X_fast в данный момент оно еще не находится в обращении. Это 9X_efficiency объясняет действия, предпринимаемые алгоритмом 9X_slow в случае sieve_base == current_prime_squared (что, кстати, подразумевает sieve[0] == 0).

Теперь 9X_performance случай sieve[0] == 0 && sieve_base < current_prime_squared легко объясним: это означает, что 9X_performance sieve_base не может быть кратным любому из простых 9X_tuning чисел, меньших текущего простого числа, иначе 9X_faster он был бы помечен как составной. Я также 9X_algorithm-design не могу быть кратным текущему простому числу, так 9X_slow как его значение меньше, чем квадрат текущего 9X_algorithm-design простого числа. Следовательно, это должен 9X_performance быть новый прайм.

Алгоритм, очевидно, вдохновлен 9X_prime-number Решетом Эратосфена, но в равной степени 9X_efficiency очевидно, что он сильно отличается. Сито 9X_tuning Эратосфена получает свою превосходную скорость 9X_tuning из-за простоты своих элементарных операций: одно 9X_performance единственное добавление индекса и одно сохранение 9X_perfomance для каждого шага операции - это все, что 9X_algorithm он делает в течение длительного периода 9X_fast времени.

Вот простое несегментированное сито 9X_tuning Эратосфена, которое я обычно использую для 9X_prime-number просеивания простых чисел коэффициента в 9X_primes коротком диапазоне, то есть до 2 ^ 16. Для 9X_algorithm этого сообщения я изменил его, чтобы он 9X_fast работал больше 2 ^ 16, заменив int на ushort

static List small_odd_primes_up_to (int n) { var result = new List(); if (n < 3) return result; int sqrt_n_halved = (int)(Math.Sqrt(n) - 1) >> 1, max_bit = (n - 1) >> 1; var odd_composite = new bool[max_bit + 1]; for (int i = 3 >> 1; i <= sqrt_n_halved; ++i) if (!odd_composite[i]) for (int p = (i << 1) + 1, j = p * p >> 1; j <= max_bit; j += p) odd_composite[j] = true; result.Add(3); // needs to be handled separately because of the mod 3 wheel // read out the sieved primes for (int i = 5 >> 1, d = 1; i <= max_bit; i += d, d ^= 3) if (!odd_composite[i]) result.Add((i << 1) + 1); return result; } 

При просеивании 9X_prime-number первых 10000 простых чисел типичный кэш 9X_tuning L1 размером 32 КиБайт будет превышен, но 9X_tuning функция по-прежнему работает очень быстро 9X_android-performance (доли миллисекунды даже в C#).

Если вы сравните 9X_perfomance этот код с deque sieve, то легко увидите, что 9X_prime-number операции deque sieve намного сложнее, и 9X_performance он не может эффективно амортизировать свои 9X_primes накладные расходы, потому что он всегда 9X_faster выполняет кратчайший возможный отрезок пересечения 9X_performance подряд (ровно одно вычеркивание после пропуска 9X_efficiency всех уже вычеркнутых кратных).

Примечание: в 9X_fast коде C# используется int вместо uint, потому что 9X_algorithm более новые компиляторы имеют привычку генерировать 9X_faster некачественный код для uint, вероятно, для того, чтобы 9X_speed подтолкнуть людей к целым числам со знаком 9X_android-performance ... В версии C++ В приведенном выше коде, естественно, я 9X_performance-tuning использовал unsigned; тест должен был быть на C++, потому 9X_efficiency что я хотел, чтобы он был основан на предположительно 9X_speed адекватном типе двухсторонней очереди (std::deque; при 9X_perfomance использовании unsigned short не было увеличения производительности). Вот 9X_performance-tuning цифры для моего ноутбука Haswell (VC++ 2015 9X_performance-tuning / x64):

deque vs simple: 1.802 ms vs 0.182 ms deque vs simple: 1.836 ms vs 0.170 ms deque vs simple: 1.729 ms vs 0.173 ms 

Примечание: время C# почти в два 9X_slow раза превышает тайминги C++, что довольно 9X_prime-number хорошо для C# и показывает, что List не сутулится, даже 9X_slow если использовать его как двухстороннюю 9X_primes очередь.

Простой код сита по-прежнему выталкивает 9X_performance двухстороннюю очередь из воды, даже если 9X_performance она уже работает за пределами своего нормального 9X_algorithms рабочего диапазона (размер кэша L1 превышен 9X_android-performance на 50%, с сопутствующей перегрузкой кеша). Преобладающей 9X_perfomance частью здесь является считывание отсеянных 9X_algorithms простых чисел, и на это не сильно влияет 9X_speed проблема с кешем. В любом случае функция 9X_android-performance была разработана для просеивания факторов 9X_fast факторов, то есть уровня 0 в трехуровневой 9X_speed иерархии сита, и обычно она должна возвращать 9X_fast только несколько сотен факторов или небольшое 9X_perfomance количество тысяч. Отсюда его простота.

Производительность 9X_tuning можно повысить более чем на порядок за счет 9X_algorithm использования сегментированного сита и оптимизации 9X_primes кода для извлечения просеянных простых чисел 9X_fast (ступенчатый мод 3 и дважды развернутый 9X_prime-number или модуль 15 и развернутый один раз), и 9X_algorithms еще больше производительности может быть 9X_efficiency выжимается из кода с помощью колеса mod 9X_faster 16 или mod 30 со всеми обрезками (т.е. полная 9X_speed развертка для всех остатков). Нечто подобное 9X_slow объясняется в моем ответе на Find prime positioned prime number в Code Review, где 9X_efficiency обсуждалась аналогичная проблема. Но трудно 9X_algorithm-design увидеть смысл в улучшении времени в доли 9X_tuning миллисекунды для одноразовой задачи ...

Для 9X_perfomance некоторой точки зрения, вот тайминги C++ для 9X_algorithm-design просеивания до 100000000:

deque vs simple: 1895.521 ms vs 432.763 ms deque vs simple: 1847.594 ms vs 429.766 ms deque vs simple: 1859.462 ms vs 430.625 ms 

Напротив, сегментированное 9X_perfomance решето в C# с несколькими прибамбасами выполняет 9X_perfomance ту же работу за 95 мс (тайминги C++ недоступны, поскольку 9X_primes в настоящее время я выполняю задачи кода 9X_primes только на C#).

В интерпретируемом языке, таком 9X_slow как Python, все может выглядеть совершенно 9X_prime-number иначе, где каждая операция имеет высокую 9X_primes стоимость, а накладные расходы интерпретатора 9X_performance-tuning затмевают все различия из-за предсказанных 9X_tuning и неверно предсказанных ветвей или операций 9X_android-performance подцикла (сдвиг, сложение) по сравнению 9X_performance-tuning с несколькими циклами. ops (умножение и, возможно, даже 9X_faster деление). Это обязательно сведет на нет 9X_algorithm преимущество простоты Сита Эратосфена, и 9X_algorithms это может сделать решение deque немного 9X_faster более привлекательным.

Кроме того, во многих 9X_algorithms случаях, указанных другими респондентами 9X_android-performance в этой теме, вероятно, преобладает время вывода. Это 9X_slow совершенно другая война, где моим основным 9X_algorithm-design оружием является такой простой класс:

class CCWriter { const int SPACE_RESERVE = 11; // UInt31 + '\n' public static System.IO.Stream BaseStream; static byte[] m_buffer = new byte[1 << 16]; // need 55k..60k for a maximum-size range static int m_write_pos = 0; public static long BytesWritten = 0; // for statistics internal static ushort[] m_double_digit_lookup = create_double_digit_lookup(); internal static ushort[] create_double_digit_lookup () { var lookup = new ushort[100]; for (int lo = 0; lo < 10; ++lo) for (int hi = 0; hi < 10; ++hi) lookup[hi * 10 + lo] = (ushort)(0x3030 + (hi << 8) + lo); return lookup; } public static void Flush () { if (BaseStream != null && m_write_pos > 0) BaseStream.Write(m_buffer, 0, m_write_pos); BytesWritten += m_write_pos; m_write_pos = 0; } public static void WriteLine () { if (m_buffer.Length - m_write_pos < 1) Flush(); m_buffer[m_write_pos++] = (byte)'\n'; } public static void WriteLinesSorted (int[] values, int count) { int digits = 1, max_value = 9; for (int i = 0; i < count; ++i) { int x = values[i]; if (m_buffer.Length - m_write_pos < SPACE_RESERVE) Flush(); while (x > max_value) if (++digits < 10) max_value = max_value * 10 + 9; else max_value = int.MaxValue; int n = x, p = m_write_pos + digits, e = p + 1; m_buffer[p] = (byte)'\n'; while (n >= 10) { int q = n / 100, w = m_double_digit_lookup[n - q * 100]; n = q; m_buffer[--p] = (byte)w; m_buffer[--p] = (byte)(w >> 8); } if (n != 0 || x == 0) m_buffer[--p] = (byte)((byte)'0' + n); m_write_pos = e; } } } 

Для 9X_efficiency записи 10000 (отсортированных) чисел требуется 9X_algorithm менее 1 мс. Это статический класс, потому 9X_algorithms что он предназначен для текстового включения 9X_primes в отправку задач кодирования с минимумом 9X_slow суеты и нулевыми накладными расходами.

В 9X_speed целом я обнаружил, что это будет намного быстрее, если 9X_algorithm-design сфокусированная работа будет выполняться 9X_slow над целыми пакетами, то есть просеивать 9X_tuning определенный диапазон, затем извлекать все 9X_speed простые числа в вектор / массив, а затем 9X_perfomance извлекать весь массив , затем просеиваем 9X_algorithms следующий диапазон и так далее, вместо того, чтобы 9X_perfomance смешивать все вместе. Наличие отдельных 9X_efficiency функций, сфокусированных на определенных 9X_slow задачах, также упрощает смешивание и сопоставление, позволяет 9X_efficiency повторно использовать и упрощает разработку 9X_android-performance / тестирование.

2
3

  • ... возможно, это сделано для эффективности (для сравнения, PQ, возможно, недостаточно эффектив ...

Ответ #15

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

В Python

import gmpy p=1 for i in range(10000): p=gmpy.next_prime(p) print p 

9X_tuning

1
0

Ответ #16

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Вот мой код VB 2008, который находит все 9X_android-performance простые числа <10 000 000 за 1 минуту 27 9X_performance-tuning секунд на моем рабочем ноутбуке. Он пропускает 9X_faster четные числа и ищет только простые числа, которые 9X_efficiency меньше sqrt тестового числа. Он предназначен 9X_faster только для поиска простых чисел от 0 до 9X_efficiency контрольного значения.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim TestNum As Integer Dim X As Integer Dim Z As Integer Dim TM As Single Dim TS As Single Dim TMS As Single Dim UnPrime As Boolean Dim Sentinal As Integer Button1.Text = "Thinking" Button1.Refresh() Sentinal = Val(SentinalTxt.Text) UnPrime = True Primes(0) = 2 Primes(1) = 3 Z = 1 TM = TimeOfDay.Minute TS = TimeOfDay.Second TMS = TimeOfDay.Millisecond For TestNum = 5 To Sentinal Step 2 Do While Primes(X) <> 0 And UnPrime And Primes(X) ^ 2 <= TestNum If Int(TestNum / Primes(X)) - (TestNum / Primes(X)) = 0 Then UnPrime = False End If X = X + 1 Loop If UnPrime = True Then X = X + 1 Z = Z + 1 Primes(Z) = TestNum End If UnPrime = True X = 0 Next Button1.Text = "Finished with " & Z TM = TimeOfDay.Minute - TM TS = TimeOfDay.Second - TS TMS = TimeOfDay.Millisecond - TMS ShowTime.Text = TM & ":" & TS & ":" & TMS End Sub 

1
0

Ответ #17

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Следующий код Mathcad вычислил первый миллион 9X_tuning простых чисел менее чем за 3 минуты.

Имейте 9X_performance в виду, что это будет использовать двойные 9X_algorithm-design числа с плавающей запятой для всех чисел 9X_algorithms и в основном интерпретируется. Надеюсь, синтаксис 9X_speed понятен.

9X_Самый эффективный код для первых 10000 простых чисел?_tuning

1
0

Ответ #18

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Вот решение C++, использующее форму SoE:

#include #include typedef std::deque mydeque; void my_insert( mydeque & factors, int factor ) { int where = factor, count = factors.size(); while( where < count && factors[where] ) where += factor; if( where >= count ) factors.resize( where + 1 ); factors[ where ] = factor; } int main() { mydeque primes; mydeque factors; int a_prime = 3, a_square_prime = 9, maybe_prime = 3; int cnt = 2; factors.resize(3); std::cout << "2 3 "; while( cnt < 10000 ) { int factor = factors.front(); maybe_prime += 2; if( factor ) { my_insert( factors, factor ); } else if( maybe_prime < a_square_prime ) { std::cout << maybe_prime << " "; primes.push_back( maybe_prime ); ++cnt; } else { my_insert( factors, a_prime ); a_prime = primes.front(); primes.pop_front(); a_square_prime = a_prime * a_prime; } factors.pop_front(); } std::cout << std::endl; return 0; } 

Обратите 9X_performance-tuning внимание, что эта версия решета может вычислять 9X_efficiency простые числа бесконечно.

Также обратите 9X_algorithm-design внимание, что STL deque требует O(1) времени для 9X_android-performance выполнения push_back, pop_front и произвольного доступа через 9X_primes подписку.

Операция resize занимает O(n) время, где 9X_speed n - это количество добавляемых элементов. Благодаря 9X_algorithm тому, как мы используем эту функцию, мы 9X_android-performance можем рассматривать ее как небольшую константу.

Тело 9X_primes цикла while в my_insert выполняется O(log log n) раз, где n равно переменной 9X_algorithm maybe_prime. Это связано с тем, что выражение условия 9X_android-performance while будет оцениваться как истинное один раз 9X_perfomance для каждого простого множителя maybe_prime. См. "Divisor function" в 9X_performance Википедии.

Умножение на количество вызовов 9X_fast my_insert показывает, что требуется O(n log log n) время, чтобы 9X_performance перечислить простые числа n ... что неудивительно, временная 9X_perfomance сложность, которую предполагается иметь 9X_algorithms в Сите Эратосфена. .

Однако, хотя этот код 9X_performance эффективен, он не самый самый эффективный ... Я настоятельно рекомендую 9X_speed использовать специализированную библиотеку 9X_algorithm для генерации простых чисел, такую ​​как 9X_performance-tuning primesieve . Любое действительно эффективное, хорошо 9X_performance оптимизированное решение потребует больше 9X_slow кода, чем кто-либо захочет ввести в Stackoverflow.

1
2

  • @Will: Это сито deque. Это очень элегантно, но довольно неэффективно, и поэтому это в основном интеллектуальное любопытство, как Сито Аткина. В отличие от последнего, он может быть дей ...

Ответ #19

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Используя решето Эратосфена, вычисления 9X_algorithms выполняются намного быстрее, чем "широко 9X_algorithm известный" алгоритм простых чисел.

Используя 9X_tuning псевдокод из его вики (https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes), я могу получить 9X_performance решение на C#.

/// Get non-negative prime numbers until n using Sieve of Eratosthenes. public int[] GetPrimes(int n) { if (n <= 1) { return new int[] { }; } var mark = new bool[n]; for(var i = 2; i < n; i++) { mark[i] = true; } for (var i = 2; i < Math.Sqrt(n); i++) { if (mark[i]) { for (var j = (i * i); j < n; j += i) { mark[j] = false; } } } var primes = new List(); for(var i = 3; i < n; i++) { if (mark[i]) { primes.Add(i); } } return primes.ToArray(); } 

GetPrimes (100000000) занимает 9X_faster 2 секунды и 330 мсек.

ПРИМЕЧАНИЕ. Значение может варьироваться 9X_performance в зависимости от технических характеристик 9X_speed оборудования.

1
0

Ответ #20

Ответ на вопрос: Самый эффективный код для первых 10000 простых чисел?

Вот мой код, который находит первые 10 000 9X_primes простых чисел за 0,049655 секунды на моем 9X_speed ноутбуке, первые 1 000 000 простых чисел 9X_algorithms менее чем за 6 секунд и первые 2 000 000 9X_tuning простых чисел за 15 секунд
Небольшое объяснение. В 9X_perfomance этом методе используются 2 метода поиска 9X_android-performance простых чисел

  1. во-первых, любое непростое число является составной частью кратных простых чисел, поэтому этот код проверяет, деля контрольный номер на меньшие простые числа вместо любого числа, это уменьшает расчет как минимум в 10 раз для четырехзначного числа и еще больше за большее количество
  2. во-вторых, помимо деления на простое число, оно делится только на простые числа, которые меньше или равны корню из проверяемого числа, что значительно сокращает вычисления, это работает, потому что любое число, превышающее корень числа, будет иметь число-аналог, которое должно быть меньше корня числа, но поскольку мы уже протестировали все числа, меньшие корня, поэтому нам не нужно беспокоиться о числе, превышающем корень проверяемого числа.

Пример вывода первых 10 000 9X_slow простых чисел
https://drive.google.com/open?id=0B2QYXBiLI-lZMUpCNFhZeUphck0 https://drive.google.com/open?id=0B2QYXBiLI-lZbmRtTkZETnp6Ykk

Вот код на языке C, Введите 9X_slow 1, а затем 10 000, чтобы распечатать первые 9X_tuning 10 000 простых чисел.
Изменить: я забыл, что 9X_performance это содержит математическую библиотеку, если 9X_primes вы работаете в Windows или Visual Studio, тогда 9X_performance-tuning все должно быть в порядке, но в Linux вы 9X_algorithms должны скомпилировать код с помощью аргумента 9X_algorithms -lm, иначе код может не работать
Пример: gcc 9X_fast -Wall -o "% e" "% f" -lm

#include #include #include #include /* Finding prime numbers */ int main() { //pre-phase char d,w; int l,o; printf(" 1. Find first n number of prime numbers or Find all prime numbers smaller than n ?\n"); // this question helps in setting the limits on m or n value i.e l or o printf(" Enter 1 or 2 to get anwser of first or second question\n"); // decision making do { printf(" -->"); scanf("%c",&d); while ((w=getchar()) != '\n' && w != EOF); if ( d == '1') { printf("\n 2. Enter the target no. of primes you will like to find from 3 to 2,000,000 range\n -->"); scanf("%10d",&l); o=INT_MAX; printf(" Here we go!\n\n"); break; } else if ( d == '2' ) { printf("\n 2.Enter the limit under which to find prime numbers from 5 to 2,000,000 range\n -->"); scanf("%10d",&o); l=o/log(o)*1.25; printf(" Here we go!\n\n"); break; } else printf("\n Try again\n"); }while ( d != '1' || d != '2' ); clock_t start, end; double cpu_time_used; start = clock(); /* starting the clock for time keeping */ // main program starts here int i,j,c,m,n; /* i ,j , c and m are all prime array 'p' variables and n is the number that is being tested */ int s,x; int p[ l ]; /* p is the array for storing prime numbers and l sets the array size, l was initialized in pre-phase */ p[1]=2; p[2]=3; p[3]=5; printf("%10dst:%10d\n%10dnd:%10d\n%10drd:%10d\n",1,p[1],2,p[2],3,p[3]); // first three prime are set for ( i=4;i<=l;++i ) /* this loop sets all the prime numbers greater than 5 in the p array to 0 */ p[i]=0; n=6; /* prime number testing begins with number 6 but this can lowered if you wish but you must remember to update other variables too */ s=sqrt(n); /* 's' does two things it stores the root value so that program does not have to calaculate it again and again and also it stores it in integer form instead of float*/ x=2; /* 'x' is the biggest prime number that is smaller or equal to root of the number 'n' being tested */ /* j ,x and c are related in this way, p[j] <= prime number x <= p[c] */ // the main loop begins here for ( m=4,j=1,c=2; m<=l && n <= o;) /* this condition checks if all the first 'l' numbers of primes are found or n does not exceed the set limit o */ { // this will divide n by prime number in p[j] and tries to rule out non-primes if ( n%p[j]==0 ) { /* these steps execute if the number n is found to be non-prime */ ++n; /* this increases n by 1 and therefore sets the next number 'n' to be tested */ s=sqrt(n); /* this calaulates and stores in 's' the new root of number 'n' */ if ( p[c] <= s && p[c] != x ) /* 'The Magic Setting' tests the next prime number candidate p[c] and if passed it updates the prime number x */ { x=p[c]; ++c; } j=1; /* these steps sets the next number n to be tested and finds the next prime number x if possible for the new number 'n' and also resets j to 1 for the new cycle */ continue; /* and this restarts the loop for the new cycle */ } // confirmation test for the prime number candidate n else if ( n%p[j]!=0 && p[j]==x ) { /* these steps execute if the number is found to be prime */ p[m]=n; printf("%10dth:%10d\n",m,p[m]); ++n; s = sqrt(n); ++m; j=1; /* these steps stores and prints the new prime number and moves the 'm' counter up and also sets the next number n to be tested and also resets j to 1 for the new cycle */ continue; /* and this restarts the loop */ /* the next number which will be a even and non-prime will trigger the magic setting in the next cycle and therfore we do not have to add another magic setting here*/ } ++j; /* increases p[j] to next prime number in the array for the next cycle testing of the number 'n' */ // if the cycle reaches this point that means the number 'n' was neither divisible by p[j] nor was it a prime number // and therfore it will test the same number 'n' again in the next cycle with a bigger prime number } // the loops ends printf(" All done !!\n"); end = clock(); cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; printf(" Time taken : %lf sec\n",cpu_time_used); } 

1
0