简体   繁体   English

尝试制作Python 3质数生成器

[英]Trying to make a Python 3 prime number generator

As the title suggests, I am attempting to make a Python 3-powered prime number generator and I can't get it to work. 顾名思义,我正在尝试制作一个由Python 3驱动的素数生成器,但我无法使其正常工作。

Here is the code: 这是代码:

import random
def main():
    d=1
    x=random.randint
    while True:
        d=d+1
        if isinstance(x/d, int)==True:
            print (x)
        else: main()
main()

and the error: 和错误:

Traceback (most recent call last):
  File "/media/mint/casper-rw/ProjectsOrWork/Python/PrimeIdle.py", line 10, in <module>
    main()
  File "/media/mint/casper-rw/ProjectsOrWork/Python/PrimeIdle.py", line 7, in main
    if isinstance(x/d, int)==True:
TypeError: unsupported operand type(s) for /: 'method' and 'int'

Code is at bottom, but try to code your own based on the following suggestions, that's more educational for you: 代码是最底层的,但是请尝试根据以下建议编写自己的代码,这对您更具教育意义:

  1. x = random.randint is not actually calling randint() x = random.randint实际上没有调用randint()
  2. You want to keep generating integer candidates and testing for primality. 您想继续生成整数候选并测试素数。 You should do this in a while-loop, not by recursing into main() every single time your candidate tests composite. 您应该在while循环中执行此操作,而不是在您的候选人每次测试复合时都递归到main() That would cause unbounded stack growth and eventually overflow. 这将导致堆栈无限增长,并最终溢出。 (Never make a recursive call if you know you won't return from it). (如果您知道不会从中返回,则不要进行递归调用)。 Also, you can't easily return from a very deep chain of recursion... you're kludging by using print(x) to sidestep that. 另外,您不能轻易地从很深的递归链中return ……您正在通过使用print(x)来回避这一点。
  3. For all those reasons, and good decomposition, partition this into a generator called generate_divisor() and a predicate function is_prime() (that returns True/False). 出于所有这些原因以及良好的分解效果, is_prime()划分为一个名为generate_divisor()的生成器和一个谓词函数is_prime() (返回True / False)。
  4. Your main loop: here's how to make it non-recursive, and turn it into a while loop. 您的主循环:这是使其非递归并将其转换为while循环的方法。 For any integer x, you only need to test divisibility by (prime) divisors up to floor(sqrt(x)). 对于任何整数x,您只需要通过(质数)除数测试地板(sqrt(x))的可除性。 If it isn't divisible by any of those divisors, it's prime, so is_prime() falls-through and returns True. 如果它不能被这些除数中的任何一个整除,则它是质数,因此is_prime()会直通并返回True。
  5. Your test for divisibility: if (isinstance(x/d, int)==True) is bad, beware truncation errors on large x/d, use if (x%d == 0) to test for divisibility instead. 您的除数测试: if (isinstance(x/d, int)==True)不好,请当心较大x / d的截断错误,请使用if (x%d == 0)来测试除数。
  6. Minor: you can easily get 60% performance boost on your prime sieve by observing that for d>5, primes can only end in 1,3,7 or 9. Hence don't do d = d+1 (or d += 1 ), you're generating lots of composite divisors and diminishing few primes. 次要:通过观察d> 5,素数只能以1,3,7或9结尾,您可以很容易地在素数筛上获得60%的性能提升。因此,请勿执行d = d+1 (或d += 1 ),您将生成许多复合除数,并减少了几个素数。 (Indeed you're generating tons of composite divisors like 27 or 51, then testing divisibility by those, which is a total waste of time, since you already tested divisibility by 3 and 17.) (实际上,您要生成大量的复合除数,例如27或51,然后再用它们测试除数,这是浪费时间,因为您已经测试了3和17的除数。)

.

import random
from math import sqrt, floor

def generate_prime_candidate():
    """Generator to generate random prime candidate"""
    yield random.randint() # probably do randint(2, 2**32 -1). You decide.

def find_random_prime():
    x = generate_prime_candidate()
    while not is_prime(x):
        x = generate_prime_candidate()
    # Found one!
    print(x)
    return x

def is_prime(x):  # normally we call integers n, floats x, but whatever...
    for d in generate_divisors(floor(sqrt(x))): # only search up to sqrt(x)
        if x%d == 0:
            return False # x is composite - d is a divisor
        return True  # x is prime

def generate_divisors(dmax):
    """Generate divisors, up to a limit. We exclude numbers easily known to be composite: residue 0,2,4,5,6,8 modulo 10"""
    yield 2
    yield 3
    yield 5 # now for d>5, exclude them by residue
    d = 7
    while d<dmax:
      while (d%10) == 5: # d easily known to be composite
        d += 2 # in fact we only need to test [0,2,4,6,8] not 5, since d+=2 is skipping residue 5 anyway
      yield d
x=random.randint

doesn't assign a random integer to x , it assigns the randint function . 没有给x分配一个随机整数,它分配randint函数 You should do: 你应该做:

x = random.randint(min, max)

However, that is the least of your problems - your prime test won't work, that isn't actually a generator function and you pick a new random number on each recursive call. 但是,这是最少的问题-主测试将不起作用,实际上不是生成器函数,因此您在每个递归调用中选择一个新的随机数。

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

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