在提供的范围内仅创建一个随机素数

时间:2016-06-10 06:16:08

标签: python

我想在任何提供的范围内只创建一个随机素数。我有这段代码:

print [x for x in range(5000, 5200)
  if not [t for t in range(2, x)
    if not x % t]]

但我的程序提供了一组素数。我想修改我的代码并在任何提供的范围内只创建一个随机数,但我找不到如何做。 请帮助。

4 个答案:

答案 0 :(得分:3)

我对mathmax的解决方案的问题在于它完成所有工作以找到5000到5200之间的素数只是为了选择一个并抛弃其余的。在您找到第一个属于素数的第一个之前,随机选择5000到5200之间的唯一数字可能更有效:

import random

minimum = 5000
maximum = 5200

next((x for x in random.sample(range(minimum, maximum), maximum - minimum) if not [t for t in range(2, x) if not x % t]), None)

这大约快了18倍。通过对我们的素性测试更加智慧,我们可以获得18倍的改进:

next((x for x in random.sample(range(minimum, maximum), maximum - minimum) if not [t for t in [2] + list(range(3, int(x**0.5) + 1, 2)) if not x % t]), None)

请注意,random.sample()用于返回与random.shuffle()不同的结果,该结果在列表中运行。如果您更喜欢random.shuffle(),并且不在表达式中包含两次数字,则可以执行以下操作:

next((x for x in (lambda y: random.shuffle(y) or y)(list(range(5000, 5200))) if not [t for t in range(2, x) if not x % t]), None)

答案 1 :(得分:2)

方法1:

import random
random.choice([x for x in range(5000, 5200) if not [t for t in range(2, x) if not x % t]])

实际上你几乎就在那里,你只需要使用random.choice()

方法2:

否则,您可以使用permutation随机置换素数范围,然后选择第一个元素:

import numpy as np
np.random.permutation([x for x in range(5000, 5200) if not [t for t in range(2, x) if not x % t]])[0]

答案 2 :(得分:2)

这是迈向更有效解决方案的一步。不是根据所有可能的除数来测试每个素数的数量,而是保留一个预先生成的素数列表。

接下来,当我们准备在范围内选择随机素数时,我们使用二分法有效地找到所有有效答案的列表并随机选择一个。如果此类列表为空,请返回None

from __future__ import print_function
import bisect
import random
from itertools import takewhile


class Primes(object):
    def __init__(self):
        self.primes = [2, 3]
        self.candidate = 5

    def process_candidate(self):
        if all(self.candidate % p != 0 for p in takewhile(
            lambda x: x * x <= self.candidate, self.primes)):
            self.primes.append(self.candidate)
        self.candidate += 2

    def maybe_random_prime_from_range(self, a, b):
        if b < a:
            return None

        while self.candidate < b:
            self.process_candidate()

        ai = bisect.bisect(self.primes, a)
        bi = bisect.bisect(self.primes[ai:], b)

        try:
            return random.choice(self.primes[ai:ai+bi])
        except:
            return None

ps = Primes()

print(ps.maybe_random_prime_from_range(4000, 4200))

答案 3 :(得分:1)

你的程序几乎是正确的,只需随机选择即可。但是我可以指出它浪费了很多时间。我以有效的方式写了同样的内容

import random
from math import sqrt

def prime(x):
    if x%2==0:return False
    elif any(x%i==0 for i in xrange(3,int(sqrt(x))+1,2)):return False
    else:return True

prime_list=[x for x in xrange(5000,5200) if prime(x)]

print random.choice(prime_list)