📜  在Python查找素数的不同方法的分析

📅  最后修改于: 2021-04-27 21:13:38             🧑  作者: Mango

如果您参加竞争性编程,您可能会熟悉以下事实:与质数有关的问题是问题解决者的选择之一。在这里,我们将讨论如何优化在给定范围内检查素数的函数,并计算执行它们的时间。
按照定义,素数是一个正整数,只能被其自身和1整除。例如:2,3,5,7。但是,如果可以将一个数分解为较小的数,则称为复合数。例如:4 = 2 * 2、6 = 2 * 3
整数1既不是质数也不是复合数。检查数字是否为素数很容易,但要进行有效检查需要付出一些努力。

方法1
现在让我们使用第一个函数来检查数字(例如n)是否为质数。在这种方法中,我们将测试从2到n-1的所有除数。我们将跳过1和n。如果n被任意除数可除,则该函数将返回False,否则返回True。
以下是此方法中使用的步骤:

  1. 如果整数小于等于1,则返回False。
  2. 如果给定数字可被2到n中的任何数字整除,则该函数将返回False
  3. 否则它将返回True
Python3
# Python Program to find prime numbers in a range
import time
def is_prime(n):
    if n <= 1:
        return False
    for i in range(2,n):
        if n % i == 0:
            return False
    return True
 
# Driver function
t0 = time.time()
c = 0 #for counting
 
for n in range(1,100000):
    x = is_prime(n)
    c += x
print("Total prime numbers in range :", c)
 
t1 = time.time()
print("Time required :", t1 - t0)


Python3
# Python Program to find prime numbers in a range
import math
import time
def is_prime(n):
    if n <= 1:
        return False
 
    max_div = math.floor(math.sqrt(n))
    for i in range(2, 1 + max_div):
        if n % i == 0:
            return False
    return True
 
# Driver function
t0 = time.time()
c = 0 #for counting
 
for n in range(1,100000):
    x = is_prime(n)
    c += x
print("Total prime numbers in range :", c)
 
t1 = time.time()
print("Time required :", t1 - t0)


Python3
# Python Program to find prime numbers in a range
import math
import time
def is_prime(n):
    if n <= 1:
        return False
    if n == 2:
        return True
    if n > 2 and n % 2 == 0:
        return False
 
    max_div = math.floor(math.sqrt(n))
    for i in range(3, 1 + max_div, 2):
        if n % i == 0:
            return False
    return True
 
# Driver function
t0 = time.time()
c = 0 #for counting
 
for n in range(1,100000):
    x = is_prime(n)
    c += x
print("Total prime numbers in range :", c)
 
t1 = time.time()
print("Time required :", t1 - t0)


Python3
# Python Program to find prime numbers in a range
import time
def SieveOfEratosthenes(n):
      
    # Create a boolean array "prime[0..n]" and
    # initialize all entries it as true. A value
    # in prime[i] will finally be false if i is
    # Not a prime, else true.
    prime = [True for i in range(n+1)]
     
    p = 2
    while(p * p <= n):
          
        # If prime[p] is not changed, then it is
       # a prime
        if (prime[p] == True):
              
            # Update all multiples of p
            for i in range(p * p, n + 1, p):
                prime[i] = False
        p += 1
    c = 0
 
    # Print all prime numbers
    for p in range(2, n):
        if prime[p]:
            c += 1
    return c
 
# Driver function
t0 = time.time()
c = SieveOfEratosthenes(100000)
print("Total prime numbers in range:", c)
 
t1 = time.time()
print("Time required:", t1 - t0)


输出:

Total prime numbers in range: 9592
Time required: 60.702312707901

在上面的代码中,我们检查了从1到100000的所有数字,无论这些数字是否为质数。如图所示,它具有巨大的运行时。运行大约需要1分钟。这是一种简单的方法,但是需要大量时间才能运行。因此,它不是竞争性编程中的首选。

方法二
在此方法中,我们通过减少检查的除数来使用一个简单的技巧。我们发现,有一条细线充当镜像,如反方向显示该线下方的分解和该线上方的分解。将因子分成两半的线是数字平方根的线。如果该数字是一个完美的平方,则可以将线偏移1,并且可以得到除以的线的整数值。

36=1*36          
  =2*18
  =3*12
  =4*9
------------
  =6*6
------------
  =9*4
  =12*3
  =18*2
  =36*1

在此函数,我们计算一个整数,即max_div,它是数字的平方根,并使用Python的数学库获取其下限值。在最后一个示例中,我们从2迭代到n-1。但是在这种情况下,我们将除数减小了一半,如图所示。您需要导入math模块以获得floor和sqrt函数。
以下是此方法中使用的步骤:

  1. 如果整数小于等于1,则返回False。
  2. 现在,我们将需要检查的数字减少到给定数字的平方根。
  3. 如果给定数字可被2到该数字的平方根中的任何数字整除,则该函数将返回False
  4. 否则它将返回True

Python3

# Python Program to find prime numbers in a range
import math
import time
def is_prime(n):
    if n <= 1:
        return False
 
    max_div = math.floor(math.sqrt(n))
    for i in range(2, 1 + max_div):
        if n % i == 0:
            return False
    return True
 
# Driver function
t0 = time.time()
c = 0 #for counting
 
for n in range(1,100000):
    x = is_prime(n)
    c += x
print("Total prime numbers in range :", c)
 
t1 = time.time()
print("Time required :", t1 - t0)

输出:

Total prime numbers in range: 9592
Time required: 0.4116342067718506

在上面的代码中,我们检查了从1到100000的所有数字,无论这些数字是否为质数。与以前的方法相比,它花费的时间相对较少。这是一个有点棘手的方法,但是在代码的运行时间上却有很大的不同。因此,它是竞争性编程中的首选。
方法3
现在,我们将代码优化到下一个级别,比上一个方法花费的时间更少。您可能已经注意到,在最后一个示例中,我们遍历了每个偶数,直至达到浪费的极限。需要注意的是,除两个以外的所有偶数不能为质数。在这种方法中,我们踢出所有偶数以优化代码,并且仅检查奇数除数。
以下是此方法中使用的步骤:

  1. 如果整数小于等于1,则返回False。
  2. 如果数字等于2,它将返回True。
  3. 如果该数字大于2并被2整除,则它将返回False。
  4. 现在,我们检查了所有偶数。现在,寻找奇数。
  5. 如果给定数字可被3到该数字的平方根中的任何数字整除,并跳过所有偶数,则该函数将返回False
  6. 否则它将返回True

Python3

# Python Program to find prime numbers in a range
import math
import time
def is_prime(n):
    if n <= 1:
        return False
    if n == 2:
        return True
    if n > 2 and n % 2 == 0:
        return False
 
    max_div = math.floor(math.sqrt(n))
    for i in range(3, 1 + max_div, 2):
        if n % i == 0:
            return False
    return True
 
# Driver function
t0 = time.time()
c = 0 #for counting
 
for n in range(1,100000):
    x = is_prime(n)
    c += x
print("Total prime numbers in range :", c)
 
t1 = time.time()
print("Time required :", t1 - t0)

输出:

Total prime numbers in range: 9592
Time required: 0.23305177688598633

在上面的代码中,我们检查了从1到100000的所有数字,无论这些数字是否为质数。与运行程序的所有先前方法相比,它花费的时间相对较少。这是检查质数的最有效,最快的方法。因此,它是竞争性编程中的首选。下次在竞争性编程中尝试任何问题时,请使用此方法以获得最佳结果。
筛法
此方法将打印所有小于或等于给定数字n的素数。例如,如果n为10,则输出应为“ 2、3、5、7”。如果n为20,则输出应为“ 2、3、5、7、11、13、17、19”。
该方法被认为是生成所有小于给定数n的素数的最有效方法。它被认为是生成质数列表的最快方法。此方法不适用于检查特定数字。此方法是生成所有素数的列表的首选方法。

Python3

# Python Program to find prime numbers in a range
import time
def SieveOfEratosthenes(n):
      
    # Create a boolean array "prime[0..n]" and
    # initialize all entries it as true. A value
    # in prime[i] will finally be false if i is
    # Not a prime, else true.
    prime = [True for i in range(n+1)]
     
    p = 2
    while(p * p <= n):
          
        # If prime[p] is not changed, then it is
       # a prime
        if (prime[p] == True):
              
            # Update all multiples of p
            for i in range(p * p, n + 1, p):
                prime[i] = False
        p += 1
    c = 0
 
    # Print all prime numbers
    for p in range(2, n):
        if prime[p]:
            c += 1
    return c
 
# Driver function
t0 = time.time()
c = SieveOfEratosthenes(100000)
print("Total prime numbers in range:", c)
 
t1 = time.time()
print("Time required:", t1 - t0)

输出:

Total prime numbers in range: 9592
Time required: 0.0312497615814209

注意:所有过程所需的时间可能会因编译器而异,但不同方法所需的时间顺序将保持不变。

参考 :