Python 给定一个数n,用最大偶数找到最接近它的素数
我有一个挑战,找到最接近任意给定整数n的素数,该整数具有最大偶数位数。下面的代码可以工作并通过所有示例测试。但当数字增长过大时,它就会超时。有人能建议我如何优化它吗Python 给定一个数n,用最大偶数找到最接近它的素数,python,python-3.x,Python,Python 3.x,我有一个挑战,找到最接近任意给定整数n的素数,该整数具有最大偶数位数。下面的代码可以工作并通过所有示例测试。但当数字增长过大时,它就会超时。有人能建议我如何优化它吗 from collections import defaultdict def is_prime(n): first, i = 1, 2 if n <= first: return False while i <= (n**0.5): if n
from collections import defaultdict
def is_prime(n):
first, i = 1, 2
if n <= first:
return False
while i <= (n**0.5):
if n % i == 0:
return False
i += first
return True
def highest_prime(n):
dd = defaultdict(int)
nums = [str(x) for x in reversed(range(n)) if is_prime(x)]
is_even = (lambda x: x % 2 == 0)
for outer in nums:
for inner in outer:
if is_even(int(inner)):
dd[outer] += 1
return max(dd, key=lambda x: dd[x])
if __name__ == "__main__":
print(highest_prime(1000))
print(highest_prime(1210))
print(highest_prime(10000))
还有其他建议吗?谢谢 有非常聪明的方法来测试一个数字是否为素数(或者至少有聪明的方法可以精确到非常大的N),但是在这种情况下,当你计算到某个数字的所有素数时,你可以使用前面的素数,只检查它们作为因子:
def get_primes_list(n):
if n < 2:
return []
primes = [2]
for i in range(3,n+1):
sqroot = i**0.5
for p in primes:
if i%p == 0:
break
if p > sqroot:
primes.append(i)
break
return primes
def get_primes_列表(n):
如果n<2:
返回[]
素数=[2]
对于范围(3,n+1)内的i:
sqroot=i**0.5
对于素数中的p:
如果i%p==0:
打破
如果p>sqroot:
素数。附加(i)
打破
返回素数
如果您正在寻找比此更有效的方法(因为此方法仍然需要消耗资源,并且在达到数千万时仍需要很长时间),您最好的选择是找到一个有效的素性测试的现有实现,如前面提到的Rabin-Miller素性测试使用“Eratosthenes筛”算法,生成小于N的素数
希望这能解决你的问题
它的时间复杂性:O(n*log(log(n))
参考资料:
有两个主要的优化领域,你应该考虑。 第一是确保我们的质数检查是合理的。从中采用智能暴力方法,基本上只需检查从1开始到数字平方根的所有n的
6n-1
和6n+1
,以确定它是否为素数。(因为6n+2
,6n+4
是偶数,6n+3
可以被3整除)。我在下面的is_prime(n)
函数中添加了解释
第二个真正起作用的因素是确保始终跟踪“偶数位数的最佳结果”。想法很简单:n
位的素数最多只能有n-1
偶数,素数2除外。考虑到这一点,我们只需要确保找到可能的“最佳情况”,而不是将所有素数累加到给定的数n
,我们只需找到适合最佳情况的最高素数,从大到小。因此,我有highest\u prime\u optimized(n)
和注释。我最初计划将这个函数的时间与原始函数进行比较,但一旦原始函数运行了一分钟,我就决定终止它。这个应该能通过测试
import time
def is_prime(n):
#base cases handling
if n == 2 or n == 3: return True #handles 2, 3
if n < 2 or n%2 == 0: return False #handles 1 and even numbers
if n < 9: return True #since 1, 2, 3, 4, 6 and 8 are handled, this leaves 5 and 7.
if n%3 == 0: return False #handles multiples of 3
r = int(n**0.5) #only check upto square root
f = 5 #start from 5
while f <= r:
#print ('\t', f)
if n%f == 0: return False #essentially checks 6n - 1 for all n.
if n%(f+2) == 0: return False #essentially checks 6n + 1 for all n.
f +=6 #incrementing by 6.
return True
def max_even_digits_in_prime(n):
return (len(str(n)) - 1) or 1
def count_of_even_digits(n):
count = 0
for i in str(n):
count+= (int(i) % 2 == 0)
return count
def highest_prime_optimized(n):
best_case = (0, 0) #keeps track of highest best case number seen[1], and its count of even digits[0]
for x in range(n, 1, -1): #iterate in the reverse direction
#print(x)
if is_prime(x): #proceed for prime numbers
even_digits = count_of_even_digits(x)
max_even_digits = max_even_digits_in_prime(x)
if best_case[0] < even_digits: #update best number seen so far
best_case = (even_digits, x)
if max_even_digits == best_case[0]: #best case answer, your work is done. No need to look for more numbers.
print(best_case)
return (best_case[1])
if __name__ == "__main__":
print(highest_prime_optimized(1000))
print(highest_prime_optimized(1210))
print(highest_prime_optimized(10000))
start = time.time()
result = highest_prime_optimized(5000000)
print(result, time.time() - start)
#Output: 4888889 0.5920031070709229
导入时间
def是_prime(n):
#基本案件处理
如果n==2或n==3:返回True#句柄2,3
如果n<2或n%2==0:返回False#处理1和偶数
如果n<9:return True#因为处理了1、2、3、4、6和8,所以剩下5和7。
如果n%3==0:返回False#处理3的倍数
r=int(n**0.5)#仅检查平方根
f=5#从5开始
当你在寻找正确方向的提示或解决方案时,你想要的是一个有效的解决方案。answer有一个Rabin Miller算法的Python实现,它应该会给您一点性能提升。您可能还想更仔细地了解一下您对range
@paritossing的使用,正确的方向是fine@AndrewF如果我不反转射程,我会得到显著的提升吗?在这种情况下,我还需要将数据类型更改为有序dict。为什么素数测试效率不高,我只检查因子直到平方根。@KabirGandhiok我可以想出一种方法来切断需要检查偶数的素数的数量。这样说吧。。。一个2位素数最多可以有多少位是偶数?3号怎么样?等等(在你的例子中,第1209页可以被3整除。我猜这是错误的)这是一个有趣的关于素性检查的观点,尽管它仍然超时。对于非常大的数字,我需要在12000毫秒以下。我尝试了选择的答案,但它也超时了。@KabirGandhiok它并不意味着是最快的,只是改进了基本的暴力算法哇!太快了!!非常感谢你解释得这么好!
import time
def is_prime(n):
#base cases handling
if n == 2 or n == 3: return True #handles 2, 3
if n < 2 or n%2 == 0: return False #handles 1 and even numbers
if n < 9: return True #since 1, 2, 3, 4, 6 and 8 are handled, this leaves 5 and 7.
if n%3 == 0: return False #handles multiples of 3
r = int(n**0.5) #only check upto square root
f = 5 #start from 5
while f <= r:
#print ('\t', f)
if n%f == 0: return False #essentially checks 6n - 1 for all n.
if n%(f+2) == 0: return False #essentially checks 6n + 1 for all n.
f +=6 #incrementing by 6.
return True
def max_even_digits_in_prime(n):
return (len(str(n)) - 1) or 1
def count_of_even_digits(n):
count = 0
for i in str(n):
count+= (int(i) % 2 == 0)
return count
def highest_prime_optimized(n):
best_case = (0, 0) #keeps track of highest best case number seen[1], and its count of even digits[0]
for x in range(n, 1, -1): #iterate in the reverse direction
#print(x)
if is_prime(x): #proceed for prime numbers
even_digits = count_of_even_digits(x)
max_even_digits = max_even_digits_in_prime(x)
if best_case[0] < even_digits: #update best number seen so far
best_case = (even_digits, x)
if max_even_digits == best_case[0]: #best case answer, your work is done. No need to look for more numbers.
print(best_case)
return (best_case[1])
if __name__ == "__main__":
print(highest_prime_optimized(1000))
print(highest_prime_optimized(1210))
print(highest_prime_optimized(10000))
start = time.time()
result = highest_prime_optimized(5000000)
print(result, time.time() - start)
#Output: 4888889 0.5920031070709229