[英]Prime checker including non primes
I am trying to solve Project Euler number 7.我正在尝试解决 Project Euler 7。
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
通过列出前六个素数:2、3、5、7、11和13,我们可以看出第6个素数是13。
What is the 10 001st prime number?第 10001 个质数是多少?
First thing that came into my mind was using length of list.我首先想到的是使用列表长度。 This was very ineffective solution as it took over a minute.
这是一个非常无效的解决方案,因为它花费了超过一分钟的时间。 This is the used code.
这是使用的代码。
def ch7():
primes = []
x = 2
while len(primes) != 10001:
for i in range(2, x):
if x % i == 0:
break
else:
primes.append(x)
x += 1
print(primes[-1])
ch7()
# Output is: 104743.
This works well but I wanted to reach faster solution.这很好用,但我想找到更快的解决方案。 Therefore I did a bit of research and found out that in order to know if a number is a prime, we need to test whether it is divisible by any number up to its square root eg in order to know if 100 is a prime we dont need to divide it by every number up to 100, but only up to 10.
因此我做了一些研究,发现为了知道一个数是否是质数,我们需要测试它是否可以被任何数整除直到它的平方根,例如为了知道 100 是否是质数我们不知道需要将它除以每个数字,最多 100,但最多 10。
When I implemented this finding weird thing happened.当我实现这个发现时,奇怪的事情发生了。 The algorithm included some non primes.
该算法包括一些非素数。 To be exact 66 of them.
确切地说是其中的 66 个。 This is the adjusted code:
这是调整后的代码:
import math
primes = []
def ch7():
x = 2
while len(primes) != 10001:
for i in range(2, math.ceil(math.sqrt(x))):
if x % i == 0:
break
else:
primes.append(x)
x += 1
print(primes[-1])
ch7()
# Output is 104009
This solution takes under a second but it includes some non primes.该解决方案需要不到一秒钟的时间,但它包含一些非素数。 I used math.ceil() in order to get int instead of float but I figured it should not be a problem since it still tests by every int up to square root of x.
我使用 math.ceil() 来获取 int 而不是 float,但我认为这应该不是问题,因为它仍然测试每个 int 直到 x 的平方根。
Your solution generates a list
of primes, but doens't use that list
for anything but extracting the last element.您的解决方案会生成一个素数
list
,但除了提取最后一个元素外,不会将该list
用于任何其他用途。 We can toss that list
, and cut the time of the code in half by treating 2 as a special case, and only testing odd numbers:我们可以扔掉那个
list
,并通过将 2 视为特例并仅测试奇数来将代码时间减半:
def ch7(limit=10001): # assume limit is >= 1
prime = 2
number = 3
count = 1
while count < limit:
for divisor in range(3, int(number ** 0.5) + 1, 2):
if number % divisor == 0:
break
else: # no break
prime = number
count += 1
number += 2
return prime
print(ch7())
But if you're going to collect a list
of primes, you can use that list
to get even more speed out of the program (about 10% for the test limits in use) by using those primes as divisors instead of odd numbers:但是,如果您要收集一个素数
list
,您可以使用该list
通过使用这些素数而不是奇数作为除数来提高程序的速度(大约 10% 用于正在使用的测试限制):
def ch7(limit=10001): # assume limit is >= 1
primes = [2]
number = 3
while len(primes) < limit:
for prime in primes:
if prime * prime > number: # look no further
primes.append(number)
break
if number % prime == 0: # composite
break
else: # may never be needed but prime gaps can be arbitrarily large
primes.append(number)
number += 2
return primes[-1]
print(ch7())
BTW, your second solution, even with the + 1
fix you mention in the comments, comes up with one prime beyond the correct answer.顺便说一句,你的第二个解决方案,即使你在评论中提到了
+ 1
修复,也会在正确答案之外提出一个质数。 This is due to the way your code (mis)handles the prime 2.这是由于您的代码(错误)处理素数 2 的方式所致。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.