python中的随机素数
我现在有↓ 设置为mypython中的随机素数,python,random,generator,list-comprehension,primes,Python,Random,Generator,List Comprehension,Primes,我现在有↓ 设置为myrandprime(p,q)函数。有没有办法通过像genexp或listcomp这样的东西来压缩这一点?以下是我的功能: n = randint(p, q) while not isPrime(n): n = randint(p, q) 最好只生成素数列表,然后从该行中进行选择。 同样,对于您的代码,它命中无限循环的可能性很小,如果间隔中没有素数,或者如果randint始终选择非素数,那么while循环将永远不会结束 所以这可能更短,也不那么麻烦: import
randprime(p,q)
函数。有没有办法通过像genexp或listcomp这样的东西来压缩这一点?以下是我的功能:
n = randint(p, q)
while not isPrime(n):
n = randint(p, q)
最好只生成素数列表,然后从该行中进行选择。 同样,对于您的代码,它命中无限循环的可能性很小,如果间隔中没有素数,或者如果
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])
#初始化素数
minPrime=0
maxPrime=1000
cached_primes=[i代表范围内的i(minPrime,maxPrime),如果isPrime(i)]
#守则的其他地方
随机输入
n=random.choice([i表示缓存的\u素数中的i,如果p
这是从itertools.count()开始的-这提供了一个无限集
每个数字都被itertools.imap()映射到范围内的一个新随机数。imap类似于map,但返回的是迭代器,而不是列表-我们不想生成有限个随机数的列表
然后,找到并返回第一个匹配号码
有效工作,即使p和q相距很远-例如1和10**30,生成完整列表也不行
顺便说一句,这并不比上面的代码更有效,而且一眼就看不懂——请考虑让下一个程序员阅读你的代码,然后像上面那样去做。当你忘记了这段代码应该做什么的时候,六个月后的程序员可能就是你了
注意-在实践中,您可能希望用xrange(非range!)替换count(),例如xrange((p-q)**1.5+20)
以不超过该尝试次数(在小范围和大范围的有限测试之间进行平衡,如果成功,失败的概率不超过1/2%),否则,正如另一篇文章中所建议的,您可能会永远循环
PPS-改进:将random.randint(p,q)
替换为random.randint(p,q)| 1
-这使代码的效率提高了一倍,但消除了结果为2的可能性。因此,如果您可以使用迭代器以随机顺序(无需替换)给出从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),您的代码将永远运行。如果存在这样一个素数,此代码将保证生成一个答案,如果不存在这样一个素数,则会告诉您答案是不存在的。您显然可以使其更紧凑,但我正在尝试显示逻辑。以下是一个用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)
似乎最好生成一个介于p
和q
之间的素数列表,然后从该列表中随机选择一个。您可以通过将最低位设置为1来增加一个数字被素数的几率,从而使其成为奇数-只有一个偶数素数,即2。事实上,除2和3之外的所有素数都是ei下面的一个,或者六的倍数上面的一个。我讨厌有人在没有说明原因的情况下对一个问题进行向下投票,因为如果OP不知道问题出在哪里,他就无法修复它。@HunterMcMillen,这取决于p&q的大小。对于大数字,这会更有效。另外,如果你在做数字筛选(生成素数的最简单方法),那么你需要从1开始。各位,这个问题缺乏具体性,这里的很多来回都是由这个问题引起的。你能不能责怪这个问题而不是其他回答者?如果p和q的顺序是10**10,这可能是一个非常糟糕的主意,如果你在考虑加密,这是一个合理的尝试。我猜如果有在p
和q
之间的素数肯定会死锁。好吧,他们可能会缓存isPrime
检查,或者有一个预构建的列表可以使用。@legostrmtropr-不一定。当使用大素数时(例如,用于RSA加密),通常的方法是检查较小的数字,然后使用统计方法-请参阅(因为2048位素数的完整测试将花费数年时间)-在素数上的每次测试运行都会成功,而在非素数上的每次测试运行都有50%的机会显示该数字为非素数。确定您想要的概率有多低,并运行适当数量的测试。人们只是对加密和疯狂的大数做出了疯狂的假设。这可能是大学一年级的编程任务ion.是的,但如果给定一个没有素数的范围,我的将完成,如果给定一个只有几个素数的范围,我的运行时间将大大缩短。OP中的代码有3行,但如果p和q之间没有素数,它将死锁,因此它是不安全的。是我,我投票否决了你,因为你的答案,虽然引入了一些有用的东西,但恰恰相反关于被问到的问题-是否有任何方法可以浓缩这一点
。我承认那部分不是我的。这不是我答案的基础,只是一个脚注。欢迎你将我的代码作为脚注(或想法)纳入你的答案中@AMADANONInc.Fine-你的代码只有一行,但它的字符数仍然是原始代码的2倍,需要导入itertools,并且无法解决错误。这是压缩的吗?去掉我的代码中消除错误的部分,我的代码基本上是相同的长度(以字符为单位)就像你的一样。@legostrmtroopr但如果整数的范围非常大(通常是在人们需要时),它将不会在合理的时间内完成
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)