Самый элегантный способ генерации простых чисел [закрыто]


каков самый элегантный способ реализации этой функции:

ArrayList generatePrimes(int n)

эта функция генерирует первый n простые числа (edit: where n>1), так generatePrimes(5) возвращает ArrayList С {2, 3, 5, 7, 11}. (Я делаю это на C#, но я доволен реализацией Java - или любым другим подобным языком, если на то пошло (так что не Haskell)).

Я знаю как написать эту функцию, но когда я сделал это прошлой ночью он не так хорошо, как я надеялся. Вот что я придумал:

ArrayList generatePrimes(int toGenerate)
{
    ArrayList primes = new ArrayList();
    primes.Add(2);
    primes.Add(3);
    while (primes.Count < toGenerate)
    {
        int nextPrime = (int)(primes[primes.Count - 1]) + 2;
        while (true)
        {
            bool isPrime = true;
            foreach (int n in primes)
            {
                if (nextPrime % n == 0)
                {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime)
            {
                break;
            }
            else
            {
                nextPrime += 2;
            }
        }
        primes.Add(nextPrime);
    }
    return primes;
}

Я не слишком беспокоюсь о скорости, хотя я не хочу, чтобы это было очевидно неэффективно. Я не возражаю, какой метод используется (наивный или ситовый или что-то еще), но я хочу, чтобы он был довольно коротким и очевидным, как он работает.

Edit: спасибо всем, кто откликнулся, хотя многие не ответили на мой вопрос. Чтобы повторить, я хотел хороший чистый кусок кода, который генерировал список простых чисел. Я уже знаю как делайте это по-разному, но я склонен писать код, который не так ясен, как мог бы быть. В этой теме было предложено несколько хороших вариантов:

  • более приятная версия того, что я изначально имел (Питер Смит, jmservera и Rekreativc)
  • очень чистая реализация сита Эратосфена (starblue)
  • используйте Java BigInteger s и nextProbablePrime для очень простого кода, хотя я не могу себе представить, что это особенно эффективно (dfa)
  • используйте LINQ, чтобы лениво генерировать список простых чисел (Maghis)
  • положите много простых чисел в текстовый файл и читать их в случае необходимости (Дарин)

Edit 2: я реализовал в C# несколько методов, приведенных здесь, и еще один метод, не упомянутый здесь. Они все находят первый n простые числа эффективно (и у меня есть достойный метод нахождения предела для обеспечения сит).

25 80

25 ответов:

использовать оценку

pi(n) = n / log(n)

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

Это мое стандартное Java-сито, вычисляет первый миллион простых чисел примерно за секунду на обычном ноутбуке:

public static BitSet computePrimes(int limit)
{
    final BitSet primes = new BitSet();
    primes.set(0, false);
    primes.set(1, false);
    primes.set(2, limit, true);
    for (int i = 0; i * i < limit; i++)
    {
        if (primes.get(i))
        {
            for (int j = i * i; j < limit; j += i)
            {
                primes.clear(j);
            }
        }
    }
    return primes;
}

большое спасибо всем, кто дал полезные ответы. Вот мои реализации нескольких различных методов поиска первого n простые числа в C#. Первые два метода в значительной степени то, что было опубликовано здесь. (Названия плакатов находятся рядом с заголовком.) Я планирую сделать сито Аткина когда-нибудь, хотя я подозреваю, что это будет не так просто, как методы здесь в настоящее время. Если кто-нибудь может увидеть какой-либо способ улучшить любой из этих методов, я хотел бы знать : -)

Стандартный Метод (Питер Смит,jmservera,Rekreativc)

первое простое число 2. Добавить в список простых чисел. Следующее простое число-это следующее число, которое не делится равномерно на любое число в этом списке.

public static List<int> GeneratePrimesNaive(int n)
{
    List<int> primes = new List<int>();
    primes.Add(2);
    int nextPrime = 3;
    while (primes.Count < n)
    {
        int sqrt = (int)Math.Sqrt(nextPrime);
        bool isPrime = true;
        for (int i = 0; (int)primes[i] <= sqrt; i++)
        {
            if (nextPrime % primes[i] == 0)
            {
                isPrime = false;
                break;
            }
        }
        if (isPrime)
        {
            primes.Add(nextPrime);
        }
        nextPrime += 2;
    }
    return primes;
}

Это было оптимизировано только проверкой на делимость до квадратного корня проверяемого числа; и только проверкой нечетных чисел. Это может быть дальше оптимизирован путем тестирования только номера формы 6k+[1, 5] или 30k+[1, 7, 11, 13, 17, 19, 23, 29] или на.

решето Эратосфена (starblue)

это находит все простые числа до k. Чтобы составить список первых n числа, нам сначала нужно приблизительное значение nче-премьер. Следующий метод, как описано здесь, не этот.

public static int ApproximateNthPrime(int nn)
{
    double n = (double)nn;
    double p;
    if (nn >= 7022)
    {
        p = n * Math.Log(n) + n * (Math.Log(Math.Log(n)) - 0.9385);
    }
    else if (nn >= 6)
    {
        p = n * Math.Log(n) + n * Math.Log(Math.Log(n));
    }
    else if (nn > 0)
    {
        p = new int[] { 2, 3, 5, 7, 11 }[nn - 1];
    }
    else
    {
        p = 0;
    }
    return (int)p;
}

// Find all primes up to and including the limit
public static BitArray SieveOfEratosthenes(int limit)
{
    BitArray bits = new BitArray(limit + 1, true);
    bits[0] = false;
    bits[1] = false;
    for (int i = 0; i * i <= limit; i++)
    {
        if (bits[i])
        {
            for (int j = i * i; j <= limit; j += i)
            {
                bits[j] = false;
            }
        }
    }
    return bits;
}

public static List<int> GeneratePrimesSieveOfEratosthenes(int n)
{
    int limit = ApproximateNthPrime(n);
    BitArray bits = SieveOfEratosthenes(limit);
    List<int> primes = new List<int>();
    for (int i = 0, found = 0; i < limit && found < n; i++)
    {
        if (bits[i])
        {
            primes.Add(i);
            found++;
        }
    }
    return primes;
}

решето Сундарама

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

public static BitArray SieveOfSundaram(int limit)
{
    limit /= 2;
    BitArray bits = new BitArray(limit + 1, true);
    for (int i = 1; 3 * i + 1 < limit; i++)
    {
        for (int j = 1; i + j + 2 * i * j <= limit; j++)
        {
            bits[i + j + 2 * i * j] = false;
        }
    }
    return bits;
}

public static List<int> GeneratePrimesSieveOfSundaram(int n)
{
    int limit = ApproximateNthPrime(n);
    BitArray bits = SieveOfSundaram(limit);
    List<int> primes = new List<int>();
    primes.Add(2);
    for (int i = 1, found = 1; 2 * i + 1 <= limit && found < n; i++)
    {
        if (bits[i])
        {
            primes.Add(2 * i + 1);
            found++;
        }
    }
    return primes;
}

возрождение старого вопроса, но я споткнулся об него, играя с LINQ.

этот код требует. NET4 .0 или.NET3. 5 с параллельными расширениями

public List<int> GeneratePrimes(int n) {
    var r = from i in Enumerable.Range(2, n - 1).AsParallel()
            where Enumerable.Range(2, (int)Math.Sqrt(i)).All(j => i % j != 0)
            select i;
    return r.ToList();
}

вы находитесь на правильном пути.

некоторые комментарии

  • простые числа.Добавить(3); делает, что эта функция не работает для числа = 1

  • вам не нужно проверять деление с примерами чисел больше, чем квадрат числа, которое будет проверено.

предложил код:

ArrayList generatePrimes(int toGenerate)
{
    ArrayList primes = new ArrayList();

    if(toGenerate > 0) primes.Add(2);

    int curTest = 3;
    while (primes.Count < toGenerate)
    {

        int sqrt = (int) Math.sqrt(curTest);

        bool isPrime = true;
        for (int i = 0; i < primes.Count && primes.get(i) <= sqrt; ++i)
        {
            if (curTest % primes.get(i) == 0)
            {
                isPrime = false;
                break;
            }
        }

        if(isPrime) primes.Add(curTest);

        curTest +=2
    }
    return primes;
}

вы должны взглянуть на вероятные простые числа. В частности, взгляните на Рандомизированные Алгоритмы и тест на примитивность Миллера–Рабина.

для полноты картины вы могли бы просто использовать java.математика.BigInteger:

public class PrimeGenerator implements Iterator<BigInteger>, Iterable<BigInteger> {

    private BigInteger p = BigInteger.ONE;

    @Override
    public boolean hasNext() {
        return true;
    }

    @Override
    public BigInteger next() {
        p = p.nextProbablePrime();
        return p;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Not supported.");
    }

    @Override
    public Iterator<BigInteger> iterator() {
        return this;
    }
}

@Test
public void printPrimes() {
    for (BigInteger p : new PrimeGenerator()) {
        System.out.println(p);
    }
}

отнюдь не эффективный, но, возможно, самый читаемый:

public static IEnumerable<int> GeneratePrimes()
{
   return Range(2).Where(candidate => Range(2, (int)Math.Sqrt(candidate)))
                                     .All(divisor => candidate % divisor != 0));
}

С:

public static IEnumerable<int> Range(int from, int to = int.MaxValue)
{
   for (int i = from; i <= to; i++) yield return i;
}

на самом деле просто вариация некоторых сообщений здесь с более приятным форматированием.

Я знаю, что вы просили не-Haskell решение, но я включаю это здесь, как это относится к вопросу, а также Haskell красиво для этого типа вещей.

module Prime where

primes :: [Integer]
primes = 2:3:primes'
  where
    -- Every prime number other than 2 and 3 must be of the form 6k + 1 or 
    -- 6k + 5. Note we exclude 1 from the candidates and mark the next one as
    -- prime (6*0+5 == 5) to start the recursion.
    1:p:candidates = [6*k+r | k <- [0..], r <- [1,5]]
    primes'        = p : filter isPrime candidates
    isPrime n      = all (not . divides n) $ takeWhile (\p -> p*p <= n) primes'
    divides n p    = n `mod` p == 0

используйте простое чисел генератор для создания простых.txt, а затем:

class Program
{
    static void Main(string[] args)
    {
        using (StreamReader reader = new StreamReader("primes.txt"))
        {
            foreach (var prime in GetPrimes(10, reader))
            {
                Console.WriteLine(prime);
            }
        }
    }

    public static IEnumerable<short> GetPrimes(short upTo, StreamReader reader)
    {
        int count = 0;
        string line = string.Empty;
        while ((line = reader.ReadLine()) != null && count++ < upTo)
        {
            yield return short.Parse(line);
        }
    }
}

в этом случае я использую Int16 в сигнатуре метода, поэтому мои простые числа.текстовый файл содержит числа от 0 до 32767. Если вы хотите расширить это до Int32 или Int64 ваши простые числа.тхт может быть значительно больше.

Я могу предложить следующее решение C#. Это ни в коем случае не быстро, но очень ясно, что он делает.

public static List<Int32> GetPrimes(Int32 limit)
{
    List<Int32> primes = new List<Int32>() { 2 };

    for (int n = 3; n <= limit; n += 2)
    {
        Int32 sqrt = (Int32)Math.Sqrt(n);

        if (primes.TakeWhile(p => p <= sqrt).All(p => n % p != 0))
        {
            primes.Add(n);
        }
    }

    return primes;
}

Я оставил любые проверки - если предел отрицательный или меньше двух (на данный момент метод всегда будет возвращать два в качестве простого числа). Но это все легко исправить.

обновление

С помощью следующих двух методов расширения

public static void Do<T>(this IEnumerable<T> collection, Action<T> action)
{
    foreach (T item in collection)
    {
        action(item);
    }
}

public static IEnumerable<Int32> Range(Int32 start, Int32 end, Int32 step)
{
    for (int i = start; i < end; i += step)
    }
        yield return i;
    }
}

вы можете переписать его следующим образом.

public static List<Int32> GetPrimes(Int32 limit)
{
    List<Int32> primes = new List<Int32>() { 2 };

    Range(3, limit, 2)
        .Where(n => primes
            .TakeWhile(p => p <= Math.Sqrt(n))
            .All(p => n % p != 0))
        .Do(n => primes.Add(n));

    return primes;
}

Это менее эффективный (потому что квадратный корень, как переоценивается довольно часто), но это еще более чистый код. Можно переписать код, чтобы лениво перечислить простые числа, но это будет загромождать код совсем немного.

вот реализация решето Эратосфена В C#:

    IEnumerable<int> GeneratePrimes(int n)
    {
        var values = new Numbers[n];

        values[0] = Numbers.Prime;
        values[1] = Numbers.Prime;

        for (int outer = 2; outer != -1; outer = FirstUnset(values, outer))
        {
            values[outer] = Numbers.Prime;

            for (int inner = outer * 2; inner < values.Length; inner += outer)
                values[inner] = Numbers.Composite;
        }

        for (int i = 2; i < values.Length; i++)
        {
            if (values[i] == Numbers.Prime)
                yield return i;
        }
    }

    int FirstUnset(Numbers[] values, int last)
    {
        for (int i = last; i < values.Length; i++)
            if (values[i] == Numbers.Unset)
                return i;

        return -1;
    }

    enum Numbers
    {
        Unset,
        Prime,
        Composite
    }

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

List<int> primes=new List<int>(new int[]{2,3});
for (int n = 5; primes.Count< numberToGenerate; n+=2)
{
  bool isPrime = true;
  foreach (int prime in primes)
  {
    if (n % prime == 0)
    {
      isPrime = false;
      break;
    }
  }
  if (isPrime)
    primes.Add(n);
}

Я написал простую реализацию Эратосфена в c#, используя некоторые LINQ.

к сожалению, LINQ не обеспечивает бесконечную последовательность ints, поэтому вам нужно использовать int.MaxValue: (

мне пришлось кэшировать в анонимном типе кандидата sqrt, чтобы избежать вычисления его для каждого кэшированного простого числа (выглядит немного уродливо).

Я использую список предыдущих простых чисел до sqrt кандидата

cache.TakeWhile(c => c <= candidate.Sqrt)

и проверьте каждый Int, начиная с 2 против него

.Any(cachedPrime => candidate.Current % cachedPrime == 0)

вот код:

static IEnumerable<int> Primes(int count)
{
    return Primes().Take(count);
}

static IEnumerable<int> Primes()
{
    List<int> cache = new List<int>();

    var primes = Enumerable.Range(2, int.MaxValue - 2).Select(candidate => new 
    {
        Sqrt = (int)Math.Sqrt(candidate), // caching sqrt for performance
        Current = candidate
    }).Where(candidate => !cache.TakeWhile(c => c <= candidate.Sqrt)
            .Any(cachedPrime => candidate.Current % cachedPrime == 0))
            .Select(p => p.Current);

    foreach (var prime in primes)
    {
        cache.Add(prime);
        yield return prime;
    }
}

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

static IEnumerable<int> Primes()
{
    yield return 2;
    List<int> cache = new List<int>() { 2 };

    var primes = Enumerable.Range(3, int.MaxValue - 3)
        .Where(candidate => candidate % 2 != 0)
        .Select(candidate => new
    {
        Sqrt = (int)Math.Sqrt(candidate), // caching sqrt for performance
        Current = candidate
    }).Where(candidate => !cache.TakeWhile(c => c <= candidate.Sqrt)
            .Any(cachedPrime => candidate.Current % cachedPrime == 0))
            .Select(p => p.Current);

    foreach (var prime in primes)
    {
        cache.Add(prime);
        yield return prime;
    }
}

авторские права 2009 Санкт-Wittum 13189 Berlin в Германии в соответствии с CC-по-СА-лицензия https://creativecommons.org/licenses/by-sa/3.0/

простой, но самый элегантный способ вычисления всех простых чисел будет следующим, но этот способ медленный и затраты памяти намного выше для более высоких чисел потому что с помощью факультета (!) функция. .. но это демонстрирует вариацию теоремы Вильсона в приложении для генерации всех простых чисел по алгоритму реализовано в Python

#!/usr/bin/python
f=1 # 0!
p=2 # 1st prime
while True:
    if f%p%2:
        print p
    p+=1
    f*=(p-2)

чтобы сделать его более элегантным, вы должны переработать свой тестовый интерфейс isprime в отдельный метод, и обрабатывать петли и надбавки за пределами этого.

Я сделал это на Java, используя функциональную библиотеку, которую я написал, но поскольку моя библиотека использует те же понятия, что и перечисления, я уверен, что код адаптируется:

Iterable<Integer> numbers = new Range(1, 100);
Iterable<Integer> primes = numbers.inject(numbers, new Functions.Injecter<Iterable<Integer>, Integer>()
{
    public Iterable<Integer> call(Iterable<Integer> numbers, final Integer number) throws Exception
    {
        // We don't test for 1 which is implicit
        if ( number <= 1 )
        {
            return numbers;
        }
        // Only keep in numbers those that do not divide by number
        return numbers.reject(new Functions.Predicate1<Integer>()
        {
            public Boolean call(Integer n) throws Exception
            {
                return n > number && n % number == 0;
            }
        });
    }
});

вот пример кода python, который выводит сумму всех простых чисел ниже двух миллионов:

from math import *

limit = 2000000
sievebound = (limit - 1) / 2
# sieve only odd numbers to save memory
# the ith element corresponds to the odd number 2*i+1
sieve = [False for n in xrange(1, sievebound + 1)]
crosslimit = (int(ceil(sqrt(limit))) - 1) / 2
for i in xrange(1, crosslimit):
    if not sieve[i]:
        # if p == 2*i + 1, then
        #   p**2 == 4*(i**2) + 4*i + 1
        #        == 2*i * (i + 1)
        for j in xrange(2*i * (i + 1), sievebound, 2*i + 1):
            sieve[j] = True
sum = 2
for i in xrange(1, sievebound):
    if not sieve[i]:
        sum = sum + (2*i+1)
print sum

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

ArrayList generatePrimes(int numberToGenerate)
{
    ArrayList rez = new ArrayList();

    rez.Add(2);
    rez.Add(3);

    for(int i = 5; rez.Count <= numberToGenerate; i+=2)
    {
        bool prime = true;
        for (int j = 2; j < Math.Sqrt(i); j++)
        {
            if (i % j == 0)
            {
                    prime = false;
                    break;
            }
        }
        if (prime) rez.Add(i);
    }

    return rez;
}

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

EDIT: как отмечено в комментариях, этот алгоритм действительно возвращает неправильные значения для numberToGenerate

использование потокового программирования в Функциональная Java, Я придумал следующее. Тип Natural по сути BigInteger >= 0.

public static Stream<Natural> sieve(final Stream<Natural> xs)
{ return cons(xs.head(), new P1<Stream<Natural>>()
  { public Stream<Natural> _1()
    { return sieve(xs.tail()._1()
                   .filter($(naturalOrd.equal().eq(ZERO))
                           .o(mod.f(xs.head())))); }}); }

public static final Stream<Natural> primes
  = sieve(forever(naturalEnumerator, natural(2).some()));

теперь у вас есть значение, которое вы можете носить с собой, что бесконечный поток простых чисел. Вы можете делать такие вещи:

// Take the first n primes
Stream<Natural> nprimes = primes.take(n);

// Get the millionth prime
Natural mprime = primes.index(1000000);

// Get all primes less than n
Stream<Natural> pltn = primes.takeWhile(naturalOrd.lessThan(n));

объяснение сита:

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

вы должны иметь следующие операторы импорта:

import fj.P1;
import static fj.FW.$;
import static fj.data.Enumerator.naturalEnumerator;
import fj.data.Natural;
import static fj.data.Natural.*;
import fj.data.Stream;
import static fj.data.Stream.*;
import static fj.pre.Ord.naturalOrd;

Я лично думаю, что это довольно короткая и чистая (Java) реализация:

static ArrayList<Integer> getPrimes(int numPrimes) {
    ArrayList<Integer> primes = new ArrayList<Integer>(numPrimes);
    int n = 2;
    while (primes.size() < numPrimes) {
        while (!isPrime(n)) { n++; }
        primes.add(n);
        n++;
    }
    return primes;
}

static boolean isPrime(int n) {
    if (n < 2) { return false; }
    if (n == 2) { return true; }
    if (n % 2 == 0) { return false; }
    int d = 3;
    while (d * d <= n) {
        if (n % d == 0) { return false; }
        d += 2;
    }
    return true;
}

попробуйте этот запрос LINQ, он генерирует простые числа, как вы ожидали

        var NoOfPrimes= 5;
        var GeneratedPrime = Enumerable.Range(1, int.MaxValue)
          .Where(x =>
            {
                 return (x==1)? false:
                        !Enumerable.Range(1, (int)Math.Sqrt(x))
                        .Any(z => (x % z == 0 && x != z && z != 1));
            }).Select(no => no).TakeWhile((val, idx) => idx <= NoOfPrimes-1).ToList();
// Create a test range
IEnumerable<int> range = Enumerable.Range(3, 50 - 3);

// Sequential prime number generator
var primes_ = from n in range
     let w = (int)Math.Sqrt(n)
     where Enumerable.Range(2, w).All((i) => n % i > 0)
     select n;

// Note sequence of output:
// 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
foreach (var p in primes_)
    Trace.Write(p + ", ");
Trace.WriteLine("");

самый простой метод-это метод проб и ошибок: вы пытаетесь, если любое число между 2 и n-1 делит ваш кандидат prime n.
Первые ярлыки, конечно, a)вам нужно только проверить нечетные числа, и b) вам нужно только проверить делители до sqrt(n).

в вашем случае, когда вы также генерируете все предыдущие простые числа в процессе, вам нужно только проверить, делит ли любое из простых чисел в вашем списке, вплоть до sqrt(n).
Должно быть самым быстрым, что вы можете получить за свои деньги : -)

edit
Ладно, код, ты сам напросился. Но я предупреждаю вас : -), это 5-минутный быстрый и грязный код Delphi:

procedure TForm1.Button1Click(Sender: TObject);
const
  N = 100;
var
  PrimeList: TList;
  I, J, SqrtP: Integer;
  Divides: Boolean;
begin
  PrimeList := TList.Create;
  for I := 2 to N do begin
    SqrtP := Ceil(Sqrt(I));
    J := 0;
    Divides := False;
    while (not Divides) and (J < PrimeList.Count) 
                        and (Integer(PrimeList[J]) <= SqrtP) do begin
      Divides := ( I mod Integer(PrimeList[J]) = 0 );
      inc(J);
    end;
    if not Divides then
      PrimeList.Add(Pointer(I));
  end;
  // display results
  for I := 0 to PrimeList.Count - 1 do
    ListBox1.Items.Add(IntToStr(Integer(PrimeList[I])));
  PrimeList.Free;
end;

чтобы узнать первые 100 простых чисел, можно рассмотреть следующий код java.

int num = 2;
int i, count;
int nPrimeCount = 0;
int primeCount = 0;

    do
    {

        for (i = 2; i <num; i++)
        {

             int n = num % i;

             if (n == 0) {

             nPrimeCount++;
         //  System.out.println(nPrimeCount + " " + "Non-Prime Number is: " + num);

             num++;
             break;

             }
       }

                if (i == num) {

                    primeCount++;

                    System.out.println(primeCount + " " + "Prime number is: " + num);
                    num++;
                }


     }while (primeCount<100);

Я получил это, впервые прочитав "сито Аткина" на Wikki плюс некоторые предыдущие мысли, которые я дал этому - я трачу много времени на кодирование с нуля и полностью обнуляюсь, когда люди критикуют мой компилятор, очень плотный стиль кодирования + я даже не сделал первую попытку запустить код ... многие из парадигмы, которые я научился использовать здесь, просто читать и плакать, получить то, что вы можете.

быть абсолютно и полностью уверены, чтобы проверить все это перед использованием, для конечно, не показывайте его никому-это для чтения и рассмотрения идей. Мне нужно, чтобы инструмент primality работал, поэтому я начинаю каждый раз, когда мне нужно что-то работать.

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

Я буду работать над моей версией завтра.

package demo;
// This code is a discussion of an opinion in a technical forum.
// It's use as a basis for further work is not prohibited.
import java.util.Arrays;
import java.util.HashSet;
import java.util.ArrayList;
import java.security.GeneralSecurityException;

/**
 * May we start by ignores any numbers divisible by two, three, or five
 * and eliminate from algorithm 3, 5, 7, 11, 13, 17, 19 completely - as
 * these may be done by hand. Then, with some thought we can completely
 * prove to certainty that no number larger than square-root the number
 * can possibly be a candidate prime.
 */

public class PrimeGenerator<T>
{
    //
    Integer HOW_MANY;
    HashSet<Integer>hashSet=new HashSet<Integer>();
    static final java.lang.String LINE_SEPARATOR
       =
       new java.lang.String(java.lang.System.getProperty("line.separator"));//
    //
    PrimeGenerator(Integer howMany) throws GeneralSecurityException
    {
        if(howMany.intValue() < 20)
        {
            throw new GeneralSecurityException("I'm insecure.");
        }
        else
        {
            this.HOW_MANY=howMany;
        }
    }
    // Let us then take from the rich literature readily 
    // available on primes and discount
    // time-wasters to the extent possible, utilizing the modulo operator to obtain some
    // faster operations.
    //
    // Numbers with modulo sixty remainder in these lists are known to be composite.
    //
    final HashSet<Integer> fillArray() throws GeneralSecurityException
    {
        // All numbers with modulo-sixty remainder in this list are not prime.
        int[]list1=new int[]{0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,
        32,34,36,38,40,42,44,46,48,50,52,54,56,58};        //
        for(int nextInt:list1)
        {
            if(hashSet.add(new Integer(nextInt)))
            {
                continue;
            }
            else
            {
                throw new GeneralSecurityException("list1");//
            }
        }
        // All numbers with modulo-sixty remainder in this list are  are
        // divisible by three and not prime.
        int[]list2=new int[]{3,9,15,21,27,33,39,45,51,57};
        //
        for(int nextInt:list2)
        {
            if(hashSet.add(new Integer(nextInt)))
            {
                continue;
            }
            else
            {
                throw new GeneralSecurityException("list2");//
            }
        }
        // All numbers with modulo-sixty remainder in this list are
        // divisible by five and not prime. not prime.
        int[]list3=new int[]{5,25,35,55};
        //
        for(int nextInt:list3)
        {
            if(hashSet.add(new Integer(nextInt)))
            {
                continue;
            }
            else
            {
                throw new GeneralSecurityException("list3");//
            }
        }
        // All numbers with modulo-sixty remainder in
        // this list have a modulo-four remainder of 1.
        // What that means, I have neither clue nor guess - I got all this from
        int[]list4=new int[]{1,13,17,29,37,41,49,53};
        //
        for(int nextInt:list4)
        {
            if(hashSet.add(new Integer(nextInt)))
            {
                continue;
            }
            else
            {
                throw new GeneralSecurityException("list4");//
            }
        }
        Integer lowerBound=new Integer(19);// duh
        Double upperStartingPoint=new Double(Math.ceil(Math.sqrt(Integer.MAX_VALUE)));//
        int upperBound=upperStartingPoint.intValue();//
        HashSet<Integer> resultSet=new HashSet<Integer>();
        // use a loop.
        do
        {
            // One of those one liners, whole program here:
            int aModulo=upperBound % 60;
            if(this.hashSet.contains(new Integer(aModulo)))
            {
                continue;
            }
            else
            {
                resultSet.add(new Integer(aModulo));//
            }
        }
        while(--upperBound > 20);
        // this as an operator here is useful later in your work.
        return resultSet;
    }
    // Test harness ....
    public static void main(java.lang.String[] args)
    {
        return;
    }
}
//eof

попробуйте этот код.

protected bool isPrimeNubmer(int n)
    {
        if (n % 2 == 0)
            return false;
        else
        {
            int j = 3;
            int k = (n + 1) / 2 ;

            while (j <= k)
            {
                if (n % j == 0)
                    return false;
                j = j + 2;
            }
            return true;
        }
    }
    protected void btn_primeNumbers_Click(object sender, EventArgs e)
    {
        string time = "";
        lbl_message.Text = string.Empty;
        int num;

        StringBuilder builder = new StringBuilder();

        builder.Append("<table><tr>");
        if (int.TryParse(tb_number.Text, out num))
        {
            if (num < 0)
                lbl_message.Text = "Please enter a number greater than or equal to 0.";
            else
            {
                int count = 1;
                int number = 0;
                int cols = 11;

                var watch = Stopwatch.StartNew();

                while (count <= num)
                {
                    if (isPrimeNubmer(number))
                    {
                        if (cols > 0)
                        {
                            builder.Append("<td>" + count + " - " + number + "</td>");
                        }
                        else
                        {
                            builder.Append("</tr><tr><td>" + count + " - " + number + "</td>");
                            cols = 11;
                        }
                        count++;
                        number++;
                        cols--;
                    }
                    else
                        number++;
                }
                builder.Append("</table>");
                watch.Stop();
                var elapsedms = watch.ElapsedMilliseconds;
                double seconds = elapsedms / 1000;
                time = seconds.ToString();
                lbl_message.Text = builder.ToString();
                lbl_time.Text = time;
            }
        }
        else
            lbl_message.Text = "Please enter a numberic number.";

        lbl_time.Text = time;

        tb_number.Text = "";
        tb_number.Focus();
    }

вот код aspx.

<form id="form1" runat="server">
    <div>
        <p>Please enter a number: <asp:TextBox ID="tb_number" runat="server"></asp:TextBox></p>

        <p><asp:Button ID="btn_primeNumbers" runat="server" Text="Show Prime Numbers" OnClick="btn_primeNumbers_Click" />
        </p>
        <p><asp:Label ID="lbl_time" runat="server"></asp:Label></p>
        <p><asp:Label ID="lbl_message" runat="server"></asp:Label></p>
    </div>
</form>

результаты: 10000 простых чисел менее чем за одну секунду!--3-->

100000 простых чисел за 63 секунды

скриншот первых 100 простых чисел enter image description here