我目前已将↓设为我的randprime(p,q)
功能。有没有办法通过像 genexp 或 listcomp 之类的东西来缩小它?这是我的职责:
n = randint(p, q)
while not isPrime(n):
n = randint(p, q)
答案 0 :(得分:4)
最好只生成素数列表,然后从该行中选择。
就像你的代码一样,如果在区间内没有素数,或者如果randint
总是选择非素数,则while
循环将会触及一个无限循环的可能性很小。永远不会结束。
所以这可能更短,更少麻烦:
import random
primes = [i for i in range(p,q) if isPrime(i)]
n = random.choice(primes)
这样做的另一个好处是,如果区间内没有素数,则不会出现死锁的可能性。如上所述,这可能会很慢,具体取决于范围,所以如果你提前缓存素数会更快:
# initialising primes
minPrime = 0
maxPrime = 1000
cached_primes = [i for i in range(minPrime,maxPrime) if isPrime(i)]
#elsewhere in the code
import random
n = random.choice([i for i in cached_primes if p<i<q])
同样,进一步优化是可能的,但非常依赖于您的实际代码......并且您知道他们对过早优化的看法。
答案 1 :(得分:1)
这是一个用python编写的脚本,用于在两个给定整数之间生成n个随机素数:
import numpy as np
def getRandomPrimeInteger(bounds):
for i in range(bounds.__len__()-1):
if bounds[i + 1] > bounds[i]:
x = bounds[i] + np.random.randint(bounds[i+1]-bounds[i])
if isPrime(x):
return x
else:
if isPrime(bounds[i]):
return bounds[i]
if isPrime(bounds[i + 1]):
return bounds[i + 1]
newBounds = [0 for i in range(2*bounds.__len__() - 1)]
newBounds[0] = bounds[0]
for i in range(1, bounds.__len__()):
newBounds[2*i-1] = int((bounds[i-1] + bounds[i])/2)
newBounds[2*i] = bounds[i]
return getRandomPrimeInteger(newBounds)
def isPrime(x):
count = 0
for i in range(int(x/2)):
if x % (i+1) == 0:
count = count+1
return count == 1
#ex: get 50 random prime integers between 100 and 10000:
bounds = [100, 10000]
for i in range(50):
x = getRandomPrimeInteger(bounds)
print(x)
答案 2 :(得分:0)
因此,如果你可以使用迭代器以随机顺序从p到q给出整数(没有替换),那将会很棒。我一直无法找到办法。以下将给出该范围内的随机整数,并将跳过已经测试过的任何内容。
import random
fail = False
tested = set([])
n = random.randint(p,q)
while not isPrime(n):
tested.add(n)
if len(tested) == p-q+1:
fail = True
break
while n in s:
n = random.randint(p,q)
if fail:
print 'I failed'
else:
print n, ' is prime'
这样做的一大优点是,如果说你测试的范围只是(14,15),你的代码就会永远运行。如果存在这样的素数,则保证该代码产生答案,并告诉您如果不存在这样的素数则不存在。你显然可以使它更紧凑,但我试图显示逻辑。
答案 3 :(得分:-1)
next(i for i in itertools.imap(lambda x: random.randint(p,q)|1,itertools.count()) if isPrime(i))
这从itertools.count()开始 - 这给出了无限集。
通过itertools.imap()将每个数字映射到范围内的新随机数。 imap就像map,但是返回一个迭代器,而不是一个列表 - 我们不想生成一个无限随机数的列表!
然后,找到第一个匹配的号码,然后返回。
即使p和q相距很远,也能有效地工作 - 例如1和10 ** 30,生成完整列表不会做!
顺便说一下,这并不比上面的代码更有效,并且一目了然更难理解 - 请考虑下一个程序员必须阅读你的代码,然后就像你一样在上面做了。当你忘记了这段代码应该做的事情时,程序员可能在六个月内成为你!
P.S - 实际上,您可能希望将count()替换为xrange(NOT range!),例如xrange((p-q)**1.5+20)
不要超过那个尝试次数(在小范围和大范围的有限测试之间取得平衡,如果成功则失败的概率不超过1/2%),否则,如同在另一篇文章,你可能会永远循环。
PPS - 改进:将random.randint(p,q)
替换为random.randint(p,q)|1
- 这使代码效率提高了两倍,但消除了结果为2的可能性。