eratosthenes_用python中的eratosthenes筛子查找素数

eratosthenes

Prime numbers have been understood at least since the Ancient Greeks, and possibly since the Ancient Egyptians. In modern times their study has intensified greatly due to their usefulness, notably in encryption, and because computers enable them to be calculated to a massively higher level than could be done by hand.

质数至少自古希腊人以来就已被理解,并且可能自古埃及人以来就已被理解。 在现代,由于其实用性,特别是在加密方面,并且由于计算机使它们的计算量大大超过了手工计算的水平,因此对它们的研究大大增强。

The best know (and according to Wikipedia still the most widely used) method for identifying them is the Sieve of Eratosthenes, which I will implement here in Python.

识别它们的最好的方法(据Wikipedia仍是最广泛使用的)是Eratosthenes的筛网,我将在这里用Python来实现。

Eratosthenes筛 (The Sieve of Eratosthenes)

The algorithm is described in full on Wikipedia, and you might like to take a look at the article.

该算法已在Wikipedia上进行了完整描述,您可能想看看该文章

To summarize the process:

总结过程:

  1. Create a list of integers from 2 to the highest number you want to check, marking them all as prime

    创建一个从2到要检查的最大数字的整数列表,并将它们全部标记为素数
  2. Initialize a variable p to 2 (the lowest prime)

    将变量p初始化为2(最低质数)

  3. Mark all multiples of p as composite (ie. non-prime)

    p的所有倍数标记为复合值(即非质数)

  4. Set p to the next number marked as prime

    p设置为标记为质数的下一个数字

  5. Repeat 3 and 4 until no subsequent primes are found.

    重复3和4,直到找不到后续的质数。

The algorithm as it stands has some glaring inefficiencies and the Wikipedia article cited above does include some refinements and alternatives. Nevertheless, let’s get stuck into a simple and straightforward implementation in Python.

目前的算法效率低下,上面引用的Wikipedia文章确实包含一些改进和替代方案。 尽管如此,让我们陷入Python的简单直接实现中。

编写代码 (Writing the Code)

This project consists of a single Python file called sieveoferatosthenes.py which you can clone/download the Github repository.

该项目包含一个名为sieveoferatosthenes.py的 Python文件,您可以克隆/下载Github存储库

This is the entire source code listing.

这是完整的源代码清单。

PRIME_COL = "\x1B[32m"
COMPOSITE_COL = "\x1B[31m"
RESET_COL = "\x1B[0m"


def main():


    """
    The main function creates and runs the sieve, using the various other functions below.
    """


    print("-------------------------")
    print("| codedrome.com         |")
    print("| Sieve of Eratosthenes |")
    print("-------------------------\n")




    # Create a list of specified size, initially all set to True
    max = 200
    sieve = [True] * (max + 1)
    p = 2


    print("Initial state: all marked as prime")
    print_sieve(sieve, 10)


    print("Running Sieve of Eratosthenes...")


    while(p != -1):
        mark_multiples(sieve, max, p)
        p = find_next_prime(sieve, max, p)


    print("Composite numbers now identified")
    print(PRIME_COL + "Prime numbers" + RESET_COL)
    print(COMPOSITE_COL + "Composite numbers" + RESET_COL)
    print_sieve(sieve, 10)


def print_sieve(sieve, columncount):


    """
    Prints the sieve in columns of specified size.
    Primes and composites are printed in the colours
    specified at the top of the file, using ANSI terminal codes.
    """


    for i in range(1, len(sieve)):


        if sieve[i] == True:
            print(PRIME_COL + "%4d" % i + RESET_COL, end="")
        else:
            print(COMPOSITE_COL + "%4d" % i + RESET_COL, end="")


        if i % 10 == 0:
            print("")


def mark_multiples(sieve, max, p):


    """
    Given a prime, mark all its multiples as False (ie non-prime or composite)
    up to the given maximum.
    """


    multiplier = 2
    i = p * multiplier


    if i <= max:
        while(i <= max):
            sieve[i] = False
            multiplier+=1
            i = p * multiplier


def find_next_prime(sieve, max, current):


    """
    Iterates remaining part of sieve to find next prime.
    Returns it if found, or -1 if it gets to the end
    without finding any more primes.
    """


    for i in range(current + 1, max + 1):
        if sieve[i] == True:
            return i


    return -1;


#-----------------------------------------------------


main()

Firstly we have some strange looking variable initialisations (with uppercase names to signify that they should be regarded as constants) which are used to output composite and prime numbers in red and green respectively, using ANSI codes.

首先,我们有一些看起来很奇怪的变量初始化(大写的名称表示应将它们视为常量),这些变量用于分别使用ANSI代码以红色和绿色输出复合和素数。

In main we create a max variable to specify how far we want to go in our prime hunt, and then create a list of Booleans of that size, all set to True for the time being. As you may have realised, although the Sieve of Eratosthenes is usually described as an algorithm for identifying prime numbers it is actually the opposite. It starts off with the assumption that all numbers are prime, and then identifies the ones that are not. This initial state is printed to emphasise the process.

main我们创建一个max变量来指定我们要进行素数搜寻的距离,然后创建一个具有该大小的布尔值列表,暂时都设置为True。 您可能已经意识到,尽管Eratosthenes筛通常被描述为用于识别素数的算法,但实际上是相反的。 首先假设所有数字都是质数,然后再确定不是。 打印此初始状态以强调该过程。

We then enter a while loop, calling functions to flag multiples of p as composite and then getting the next prime in the list. The latter function returns -1 if there are none left, so that value is used as the exit condition of the while loop.

然后,我们进入while循环,调用函数以将p倍数标记为复合,然后获取列表中的下一个质数。 如果没有剩余的函数,则后一个函数返回-1,因此该值用作while循环的退出条件。

The process is now complete so we just call print_sieve again to show which numbers are prime and which are composite.

现在该过程已完成,因此我们只需再次调用print_sieve即可显示哪些数字是质数,哪些是复合数字。

Now we just need to implement the three functions called in main, starting with print_sieve. This iterates the data, outputting the values in red or green to indicate their status as composite or prime — note we start off with a key to the colour coding.

现在我们只需要实现main调用的三个函数,从print_sieve开始。 这将对数据进行迭代,以红色或绿色输出值,以指示其状态为复合或质数-请注意,我们首先使用了颜色编码键。

The function takes a columncount argument so if we have run out of columns we print a new line to go back to the first column. This is calculated using the modulus (remainder) operator %, for example if we asked for 10 columns and have just printed value 30, 30 % 10 = 0 so we call print(“”) with an empty string so it will just print a new line. For any value of i which is not a multiple of 10 the modulus will be non-zero so print(“”) is not called.

该函数采用columncount参数,因此,如果我们用完了所有列,我们将打印新行以返回到第一列。 这是使用模数(余数)运算符%计算的,例如,如果我们要求10列并且仅打印了30、30%10 = 0,那么我们用空字符串调用print(“”),这样它将只打印一个新队。 对于任何不为10的倍数的i值,模量将为非零,因此不会调用print(“”)。

Now let’s move on to the core function of this entire project: mark_multiples.

现在,让我们继续整个项目的核心功能: mark_multiples

Firstly we create a couple of variables, one for the multiplier set to 2 and another called i which is set to p * multiplier to give us the first value to flag as non-prime. After checking that i hasn’t blown through the end of the data we enter a while loop, setting the flag to false, incrementing the multiplier, and then calculating the next value of i or in other words the next value to be flagged as non-prime. The loop continues until we run past max.

首先,我们创建了两个变量,其中一个变量的multiplier设置为2,另一个变量i的设定为p * multiplier以使我们将第一个值标记为非素数。 在检查完i还没有结束数据之后,我们进入一个while循环,将标志设置为false,增加乘数,然后计算i的下一个值,或者换句话说,将下一个标记为non的值-主要。 循环一直持续到我们超过最大速度为止。

Basically what we are doing here is multiplying the current prime by 2, 3, 4 etc. and marking the result as non-prime until we get past max. Note this is one of the inefficiencies in the basic algorithm — we may be marking numbers as non-prime which have already been flagged as multiples of lower primes. For example, 6 would be marked as non-prime because it is a multiple of 2, but would be marked non-prime again as a multiple of 3.

基本上,我们在这里所做的是将当前素数乘以2、3、4等,并将结果标记为非素数,直到超过最大值。 请注意,这是基本算法的低效率之一-我们可能将数字标记为非质数,而这些非质数已被标记为低质数的倍数。 例如,6将被标记为非素数,因为它是2的倍数,但将再次被标记为非素数为3的倍数。

Finally we will implement find_next_prime. This function searches through the flags for the next prime, starting at the one after the current. If one is found it is returned; if the loop completes without a prime being found the function returns -1. (Remember that in main we use -1 as the terminating condition for the while loop.)

最后,我们将实现find_next_prime 。 此功能搜索标志中的下一个素数,从当前值之后的一个素数开始。 如果找到一个,则返回它; 如果循环结束而没有找到素数,则该函数返回-1。 (请记住,在主要情况下,我们使用-1作为while循环的终止条件。)

Now we can run the program — enter this in terminal:

现在我们可以运行该程序-在终端中输入以下内容:

python3.8 sieveoferatosthenes.py

python3.8 sieveoferatosthenes.py

The program output looks like this for max = 100.

对于max = 100,程序输出如下所示。

Image for post
Image for post

First we see all the numbers in green as they are initially marked as prime, then the numbers again with the composites in red. You could call print_sieve within the loop in main if you want to see the progress of each iteration, although it might be rather tedious for this many numbers.

首先,我们看到所有数字最初都标记为质数时为绿色,然后数字再次为红色。 如果您想查看每次迭代的进度,可以在main的循环中调用print_sieve ,尽管对于这么多的数字来说可能很乏味。

翻译自: https://medium.com/explorations-in-python/finding-prime-numbers-with-the-sieve-of-eratosthenes-in-python-a1bc2fdbbf81

eratosthenes

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值