简体   繁体   English

素数查找程序的效率(c++)

[英]Efficiency of a prime number finding program(c++)

I'm wondering if there is something inefficient in this code I've made, or if there is a faster way to find prime numbers.我想知道我制作的这段代码是否效率低下,或者是否有更快的方法来查找素数。

#include <stdio.h>

int main(void)
{
    int count;

    for(int i=3; i<1000; i+=2){//search number in range of 3~999
        count=0;//init count
        for(int j=3; j*j<=i; j+=2){
            if(count==1){//if i has aliquot already, break the loop
                break;
            }
            if(i%j==0){
                count=1;//if i has aliquot, change count to 1
            }
        }
        if(count==0){
            printf("%d ", i);//if there are no aliquot, print i
        }
    }

    return 0;
}

Seems that you are using trial division , which takes O (√ n ) time to determine the primality of a single number, thus inefficient for finding all prime numbers in a range.似乎您正在使用试验除法,这需要O (√ n ) 时间来确定单个数字的素数,因此在查找范围内的所有素数时效率低下。 To find all prime numbers in a range efficiently, consider using the sieve of Eratosthenes (with time complexity O ( n log n loglog n )) or Euler's sieve (with time complexity O ( n )).要有效地查找范围内的所有素数,请考虑使用Eratosthenes 筛(时间复杂度为O ( n log n loglog n ))或欧拉筛(时间复杂度为O ( n ))。 Here are simple implementations for these two algorithms.以下是这两种算法的简单实现。

Implementation for the sieve of Eratosthenes埃拉托色尼筛的实施

bool isPrime[N + 5];

void eratosthenes(int n) {
    for (int i = 2; i <= n; ++i) {
        isPrime[i] = true;
    }
    isPrime[1] = false;
    for (int i = 2; i * i <= n; ++i) {
        if (isPrime[i]) {
            for (int j = i * i; j <= n; j += i) {
                isPrime[j] = false;
            }
        }
    }
}

Implementation for Euler's sieve欧拉筛的实现

bool isPrime[N + 5];
std::vector<int> primes;

void euler(int n) {
    for (int i = 2; i <= n; ++i) {
        isPrime[i] = true;
    }
    isPrime[1] = false;
    for (int i = 2; i <= n; ++i) {
        if (isPrime[i]) primes.push_back(i);
        for (size_t j = 0; j < primes.size() && i * primes[j] <= n; ++j) {
            isPrime[i * primes[j]] = false;
            if (i % primes[j] == 0) break;
        }
    }
}

Eratosthenes Sieve is cool, but deprecated ? Eratosthenes Sieve 很酷,但已弃用? Why not use my Prime class ?为什么不使用我的 Prime 课程? it has an incrementation method, does not not use division.它有一个增量方法,不使用除法。 Prime class describes a number through its congruences to lower primes.素数类通过其与较低素数的全等来描述一个数字。 Incrementing a prime is to increase all congruences, a new congruence is created if the integer is prime (all congruences -modulos_- differ from 0).增加一个素数是为了增加所有同余,如果整数是素数,则创建一个新同余(所有同余-模_-不同于0)。

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>

class Prime {
public :
  Prime () : n_ (2), modulos_ (std::vector<std::pair<int, int> > ())
  {
    if (!modulos_.capacity ()) modulos_.reserve (100000000);
    std::pair<int, int> p (2, 0);
    modulos_.push_back (p);
  }
  ~Prime () {}
  Prime (const Prime& i) : n_ (i.n_), modulos_ (i.modulos_)
   {}
  bool operator == (const Prime& n) const {
    return (n_ == n.n_);
  }
  bool operator != (const Prime& n) const {
    return !operator == (n);
  }
  Prime& operator = (const Prime& i) {
    n_ = i.n_,
    modulos_ = i.modulos_;
    return *this;
  }
  void write (std::ostream& os) const {
    os << n_;
  }
  void operator ++ () {
    int prime (1);
    do {
      ++n_;
      prime = 1;
      std::for_each (modulos_.begin (), modulos_.end (), [&prime] (std::pair<int, int>& p) {
        ++p.second;
        if (p.first == p.second) {
          p.second = 0;
          prime  = 0;
        }
      });
    }
    while (!prime);
    std::pair<int, int> p (n_, 0);
    modulos_.push_back (p);
  }
  bool operator < (const int& s) const {
    return n_ < s;
  }
private :
  int n_;
  std::vector<std::pair<int, int> > modulos_; 
};

Usage :用法 :

int main (int, char**) {
  Prime p;
  do {
    p.write (std::cout);
    std::cout << std::endl;
    ++p;
  }
  while (p < 20);
}

Results : 2 3 5 7 11 13 17 19结果:2 3 5 7 11 13 17 19

For the primes up to 1000, an efficient method is对于高达 1000 的素数,一种有效的方法是

cout << "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  101 103 107 109
113 127 131 137 139 149 151 157 163 167
173 179 181 191 193 197 199 211 223 227
229 233 239 241 251 257 263 269 271 277
281 283 293 307 311 313 317 331 337 347
349 353 359 367 373 379 383 389 397 401
409 419 421 431 433 439 443 449 457 461
463 467 479 487 491 499 503 509 521 523
541 547 557 563 569 571 577 587 593 599
601 607 613 617 619 631 641 643 647 653
659 661 673 677 683 691 701 709 719 727
733 739 743 751 757 761 769 773 787 797
809 811 821 823 827 829 839 853 857 859
863 877 881 883 887 907 911 919 929 937
941 947 953 967 971 977 983 991 997" << endl;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM