Подтвердить что ты не робот

Оптимизация кода простых чисел?

Я написал этот код, чтобы показать простые числа от 1 до 100. Единственное условие - не использовать функции, весь код должен быть встроенным. Я бы спросил, могу ли я улучшить (оптимизировать) его гораздо больше?

#include<iostream>

using namespace std;

int main() {

    int i=2,j=2;

    cout<<"Prime numbers between 1 and 100 are:"<<endl;
    cout<<"2"<<"\t";
    while(i!=100) {
        for(int j=2;j<i;j++) {
            if(i%j==0)
            break;

            if(j==i-1)
            cout<<i<<"\t";
        }

        i++;
    }

    cout<<endl;
    system("pause");
    return 0;
}
4b9b3361

Ответ 1

Вы проверяете каждое число от 2 до 100. Но так как 2 является единственным четным простым числом, вы можете пропустить каждое четное число после 2. Это происходит как для i, так и для j. Итак, запустите i и j в 3 и увеличите их на 2.

#include<iostream>

using namespace std;

int main() {
    cout<<"Prime numbers between 1 and 100 are:"<<endl;
    cout<<"2"<<"\t";
    for (int i=3; i<100;i+=2) {
        // This loop stops either when j*j>i or when i is divisible by j.
        // The first condition means prime, the second, not prime.
        int j=3;
        for(;j*j<=i && i%j!=0; j+=2); // No loop body

        if (j*j>i) cout << i << "\t";
    }
    cout<<endl;
    return 0;
}

В дополнение к трюку, упомянутому выше, я добавил условие j*j<=i, которое логически является тем же самым, что и j<=sqrt(i). Нет необходимости вычислять квадратный корень, когда вы можете сделать простое умножение.

Ответ 2

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

Это нехорошо.

Прежде всего, вам нужно только проверить j <= sqrt(i), так как, например, 7 никогда не разделит 12 без отдыха.

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

Ответ 3

Вы можете оптимизировать существующий код:

  • В цикле while вы должны сделать шаг 2, чтобы вы не тестировали четные числа.
  • В цикле for вы должны остановиться, когда достигнете квадратного корня числа, которое вы тестируете.

Вы можете использовать другой метод:

На сите Erastoses просто удаляя числа, разделяемые на 2,3 и 5, значительно уменьшилось бы количество раз, которое вам нужно было бы проверить на простоту.

Ответ 4

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

int i,j,sq;
int min;
for(sq = 2; sq <= 10; sq++)
{
  min = (sq-1)*(sq-1);
  min = min + (min+1)%2; //skip if it even, so we always start on odd
  for(i = min; i < sq*sq; i+=2)
  {
    for(j = 3; j <= sq; j+=2)
    {
      if (i%j == 0)
        bad;
    }
  }
}

обратите внимание, что цикл sq не добавляет времени, потому что он пропорционально сокращает внутренние циклы.

Ответ 5

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

int main() {
    cout << "Prime numbers are:" << endl << "2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97" << endl;
    return 0;
}

Ответ 6

Зависит от той оптимизации, которую вы хотите сделать. Ваше как можно лучше, я вижу, что вы сначала оптимизируете пространство, а время второе (ну, близко - пока вы слушаете @Paul, это будет). Если вы отмените приоритеты, сито Erastothenes будет быстрее (но займет до 100 булевых точек вашей памяти).

Ответ 7

Две простые оптимизации, которые вы могли бы сделать:

cout << 2 << '\t';
for (int i = 3; i <= 100; ++i) {
    for (int j = 3, l = (int)sqrt(i); j <= l; j += 2) {
        if (i % j == 0) {
            cout << i << '\t';
            break;
        } 
} 

Что я сделал:

Математика:

  • Остановитесь, когда j > sqrt(i), нет необходимости идти дальше этого. Обратите внимание, однако, что sqrt является дорогостоящей функцией; для вашего небольшого образца (от 1 до 100), он может (читал, конечно) стоить вам больше, чтобы использовать его.
  • Проверить только нечетные числа; do j += 2 вместо того, чтобы увеличивать j один за другим

Micro-оптимизации:

  • Используйте ++i вместо i++; последний имеет временную переменную, в которой он сохраняет исходное значение i; первый не делает.
  • Печать '\t' как символ не как строка "\t".

(Эти микрооптимизации, вероятно, автоматически создаются компилятором, но нет никакого вреда в знании о них.)

Ответ 8

Самый эффективный способ добиться этого - Сито Эратосфена. Здесь инкрементная версия, специально предназначенная для создания простых чисел до 100, одна за другой (максимум до 120, потому что 121 == 11 * 11).

printf("2 ");
int m3=9, m5=25, m7=49, i=3;
for( ; i<100; i+=2 )
{
    if( i!=m3 && i!=m5 && i!=m7) printf("%d ", i);
    else
    {
        if( i==m3 ) m3+=6;
        if( i==m5 ) m5+=10;
        if( i==m7 ) m7+=14;
    }
}

Ответ 9

/*** Return an array of primes from 2 to n. ***/
int[] function nPrimes(int n) {
   int primes[];  //memory allocation may be necessary depending upon language.
   int p = 0;
   bool prime;
   for (int i = 2; i <= n; i++) {
       prime = true;
       //use (j <= (int)sqrt(i)) instead of (j < i) for cost savings.
       for (int j = 2; j <= (int)sqrt(i); j++)  {
           if (i % j == 0) {
               prime = false;
               break;
           }
       }
       if (prime) {
           primes[p++] = i;
       }    
   }
   return primes;
}