【问题标题】:Faster way to find the biggest prime number less than or equal to the given input找到小于或等于给定输入的最大素数的更快方法
【发布时间】:2021-10-24 16:16:59
【问题描述】:

给定一个整数,我想找到它下面最大的素数。例如:

input 20 -> output 19
input 100 -> output 97.

我已经有了下面给出的简单程序,但我很好奇如何让它更快。

def isPrime(x):
  for j in range(2,int(x**0.5)+1):
    if x%j==0:
      return False
  return True

def findPrimeNum(num):
  for i in range(num-1,1,-1):
    if isPrime(i):
      return i

findPrimeNum(600851475143)  # -> 600851475067

【问题讨论】:

  • 除 2 以外,素数都是奇数。您的代码没有利用这一事实。因此,有一种简单的方法可以让它至少快 50%。由于您的代码正在运行,请考虑在 Code Review 而不是此处发布此问题 - 但如果您这样做,请先阅读他们的发布指南。
  • 你可以试试埃拉托色尼筛。
  • 我很困惑,这被标记为一个关于isPrime 的问题的重复,当这个问题是关于寻找下一个素数,而不是测试给定的数字是素数.
  • @PresidentJamesK.Polk 完成。

标签: python algorithm primes


【解决方案1】:

最好的方法可能是复制几个数论库用来实现高效的 next_prime 函数的方法。基本布局与您的相同:一个 isPrime(x) 函数和一个倒计时循环。这些提供了两个优化领域。

优化 isPrime 推荐的方法是使用 Python 的数论库,如 gmpy2,并使用 Miller-Rabin 等概率素数测试重复适当的次数。这可以很好地适应更大的数字,您甚至可以通过使用 Miller-Rabin 和 enough small bases 来获得确定性素数测试。

在可能的素数上优化迭代 已经有一个comprehensive guide for optimizing next_prime in practice,它基本上涉及选择前 k 个素数(例如 2、3 和 5)并计算所有可能是素数的余数。然后,不是迭代所有较小的数字,而是只在这些残基之间跳转。为了适应 previousPrime,我们只是在相反方向的残基之间跳转。

对于 2、3 和 5,这些残基 mod 30 是 L = [1, 7, 11, 13, 17, 19, 23, 29]。对于一个整数 x > 30,比如 x = 30*q + r,你可以在 L 上进行二分搜索,寻找小于 r 的最大元素,然后在这个列表中向后迭代:

residues = [1, 7, 11, 13, 17, 19, 23, 29]
small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]


def prevPrime(num):
    if num <= 2:
        return 0
    q, r = divmod(num, 30)
    if q == 0:
        return small_primes[bisect_left(small_primes, num) - 1]
    num = 30 * q
    if r <= 2:
        num -= 30
        q -= 1
        idx = len(residues) - 1
    else:
        idx = bisect_left(residues, r) - 1
    num += residues[idx]
    while not (isPrime(num)):
        idx -= 1
        if idx < 0:
            q -= 1
            idx = len(residues) - 1
        num = 30 * q + residues[idx]
    return num

【讨论】:

    猜你喜欢
    • 2016-09-30
    • 1970-01-01
    • 2020-11-19
    • 2021-04-25
    • 1970-01-01
    • 2010-09-26
    • 2021-06-09
    • 1970-01-01
    • 2011-10-08
    相关资源
    最近更新 更多