Простое число искатель


Есть еще одно упражнение, от мышления в C++.
На этот раз он просит этого:

Напишите программу, которая использует два вложенных циклов и оператор модуля (%) для выявления и печати простых чисел (целые числа, которые не делятся нацело на любое другие числа кроме себя и 1).

И вот что я думаю:

// finds all prime numbers between 2 and a number given in input.
#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {
    cout << "How many prime numbers do you want to print? ";
    int n;
    cin >> n;

    int i, j;
    bool flag = true;
    for(i = 2; i <= n; i++) {
        for(j = 2; j <= i; j++) {
            if((i % j) == 0) {
                if(i == j)
                    flag = true;
                else {
                    flag = false;
                    break;
                }
            }
        }

        if(flag)
            cout << "Prime: " << i << endl;
    }
}

Он отлично работает, но я знаю, что вы думаете об. Спасибо за отзыв!



7027
3
задан 11 августа 2011 в 11:08 Источник Поделиться
Комментарии
7 ответов

Прости меня, что я C# разработчик, я, как описательные термины :)

Как Александр говорилось, корень является ключом к минимизации вычислений. Большую эвристическую. Другой эвристический вы можете использовать любое другое число не будет, как это будет делиться на 2. Затем, чтобы расширить на эту эвристику, можно сказать, что нет нечетные числа делятся на четные числа и поэтому может пропускать любое другое число, как ваш кратно количество теста.

for(int mightBePrime = 3; mightBePrime <= upperLimitToCheck; mightBePrime += 2)
{
bool foundAPrime = true;
for(int divisorToCheckPrime = 3; divisorToCheckPrime * divisorToCheckPrime <= mightBePrime ; divisorToCheckPrime += 2)
{
if(mightBePrime % divisorToCheckPrime == 0)
{
foundAPrime = false;
break;
}
}
}

5
ответ дан 12 августа 2011 в 01:08 Источник Поделиться

Что я думаю по поводу вашего кода:

Это небрежный кодирования.
Вы не должны использовать его. Лучше для полного определения вещи из пространства имен std. Его не так уж сложно или долго.

using namespace std;

Я бы поставил "\N" на конце линии.
Это делает вопросы на терминал похож на вопрос и ваш ответ на следующий, который на мой взгляд делает его более удобным для чтения.

    cout << "How many prime numbers do you want to print? ";

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

    int n;
cin >> n;

Лично мне не нравится '{' в конце строки. Но я понимаю, что это вещь стиль, так что я не волнует, если другие люди делают ее такой.

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

Другие уже отметили, что внутренний цикл может быть оптимизирован.

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

Этот тест не понадобится.
Это просто означает, что вы делаете дополнительную работу.

                if(i == j)

Попробуйте это:

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

struct PrimeTest
{
PrimeTest(int val)
: value(val)
{}
bool operator()(int test) const { return value%test == 0;}
int value;
};

int main()
{
std::vector<int> primes;
int maxCount;

std::cout << "Check how many numbers?\n";
std::cin >> maxCount;

for(int primeTest = 2; primeTest <= maxCount; ++primeTest)
{
// There is a loop hidden inside here.
if (std::find_if(primes.begin(), primes.end(), PrimeTest(primeTest)) == primes.end())
{ primes.push_back(primeTest);
}
}
std::copy(primes.begin(), primes.end(), std::ostream_iterator<int>(std::cout, ", "));
}

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

    for(int primeTest = 2; primeTest <= maxCount; ++primeTest)
{
std::vector<int>::iterator loop = primes.begin();
TestPrime test(primeTest);
for(;loop != primes.end(); ++loop)
{
if (test(*loop))
{ break;
}
}
if (loop == primes.end())
{ primes.push_back(primeTest);
}
}

Технически вам не нужно, чтобы проверить все числа меньше числа тестировании. Некоторые отмечали, легкая оптимизация тестирование только до квадратного корня из числа. Но еще лучшее решение-только для проверки простых чисел ниже ваш номер.

4
ответ дан 12 августа 2011 в 06:08 Источник Поделиться

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

cout << "Enter an upper bound for the prime numbers to print: "; 

3
ответ дан 12 августа 2011 в 08:08 Источник Поделиться

Если вы находите одно простое число, перебрав все цифры до его квадратного корня хорошо. Но если вы пытаетесь найти каждый Премьер-до определенного предела, то поступайте следующим образом. Держите список всех вы найдете, то, при проверке новый номер, только проверь на ранее найденные простые числа, до его квадратного корня. Так, что-то вроде этого:

std::vector<int> primes;
for(int i=2; i<=n; ++i)
{
bool is_prime = true;
int sq = sqrt((long double)i);
for (int j=0; j<primes.size() && primes[j] <= sq; ++j)
{
if (i % primes[j] == 0)
{
is_prime = false;
break;
}
}
if (is_prime) primes.push_back(i);
}

1
ответ дан 12 августа 2011 в 03:08 Источник Поделиться

В дополнение ко всему уже упомянул, вы не проверяя, является ли пользователь вводит действительное число. Как полагают в C++ часто задаваемые вопросы:

int max_prime;
while ((std::cout << "Enter an upper bound for the prime numbers to print: ")
&& !(std::cin >> max_prime)) {
std::cout << "That is not a valid number. ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

1
ответ дан 14 августа 2011 в 04:08 Источник Поделиться

Для(от J = 2; J в <= я; J++ В) должны быть для(с J = 2; J В * й <= я; к++). Нужно проверить только для делителей меньше, чем квадратный корень из Я (если есть делитель больше, чем функция sqrt(я), есть один меньше, чем функция sqrt(я)).

Поэтому цикл следует читать:

for(i = 2; i <= n; i++) 
{
bool flag = true;

for(j = 2; j * j <= i; j++)
{
if(i % j != 0)
{
flag = false;
break;
}
}

if (flag) cout << "Prime: " << i << endl;
}

0
ответ дан 11 августа 2011 в 11:08 Источник Поделиться

Вот мой Java-код для создания простых чисел, которые должны быть легко изменены, чтобы соответствовать С++ должен:

public static boolean [] createPrimes (final int MAX)
{
boolean [] primes = new boolean [MAX];
// make only odd numbers are candidates...
for (int i = 3; i < MAX; i+=2)
{
primes[i] = true;
}
// ... except the 2
primes[2] = true;

// ... iterate in steps of 2
for (int i = 3; i < MAX; i+=2)
{
/*
If a number z is already eliminated, (like 9),
because it is a multiple, (of 3), then all
multiples of that number are already
eliminated too.
*/
if (primes[i])
{
int j = 2 * i;
while (j < MAX)
{
if (primes[j])
primes[j] = false;
// in this inner loop *)
j+=i;
}
}
}
return primes;
}

Во внутреннем цикле, вы даже можете прыгать в шагов от меня, потому что после исключения кратных 3*х (3*5, 3*7, 3*11, ...) Вам не нужно исключить кратных как 5*3, в 3 раза-что-то уже ушло. Так же, если вы достигнете 7: 7*3 уже прошло как 3*7 и 7*5 а 5*7. Следует посетить/проверял только кратно выше, чем 7.

0
ответ дан 12 августа 2011 в 01:08 Источник Поделиться