如何在Python中的范围内生成非素数随机数?
我很困惑如何创建一个能够在一定范围内产生非素数的算法。我是定义函数还是创建条件语句?我希望范围内的每个数字具有相同的概率。例如,在1 - 100中,每个非素数不会有1%的几率,而是有1.35%的几率。
答案 0 :(得分:3)
现在,你对效率一无所知,这肯定会得到优化,但这应该可以解决问题。这应该是测试素数的有效算法:
import random
def isPrime(n):
if n % 2 == 0 and n > 2:
return False
return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))
def randomNonPrime(rangeMin, rangeMax):
nonPrimes = filter(lambda n: not isPrime(n), xrange(rangeMin, rangeMax+1))
if not nonPrimes:
return None
return random.choice(nonPrimes)
minMax = (1000, 10000)
print randomNonPrime(*minMax)
在返回范围内所有非素数的列表后,从非素数列表中选择一个随机值,使得范围内任何非素数的选择与该范围内的任何其他非素数一样可能
修改强>
虽然你没有问过效率,但我感到很无聊,所以我想出了一种方法,这使得(1000, 10000000)
范围内的import numpy
import sympy
def randomNonPrime(rangeMin, rangeMax):
primesInRange = numpy.fromiter(
sympy.sieve.primerange(rangeMin, rangeMax),
dtype=numpy.uint32,
count=-1
)
numbersInRange = numpy.arange(rangeMin, rangeMax+1, dtype=numpy.uint32)
nonPrimes = numbersInRange[numpy.invert(numpy.in1d(numbersInRange, primesInRange))]
if not nonPrimes.size:
return None
return numpy.random.choice(nonPrimes)
minMax = (1000, 10000000)
print randomNonPrime(*minMax)
在我的机器上花费的时间超过6秒而不是一分半钟:
k
这使用SymPy symbolic mathematics library来优化范围中素数的生成,然后使用NumPy过滤输出并选择随机非素数。
答案 1 :(得分:1)
选择的算法和想法非常依赖于您的确切用例,如@smarx所述。
max_trials
max_trials
- 通过Coupon-Collectors-Problem(wiki)的近似值设置值:每次观察每个候选人的预期样本数 import random
import math
""" Miller-Rabin primality test
source: https://jeremykun.com/2013/06/16/miller-rabin-primality-test/
"""
def decompose(n):
exponentOfTwo = 0
while n % 2 == 0:
n = n//2 # modified for python 3!
exponentOfTwo += 1
return exponentOfTwo, n
def isWitness(possibleWitness, p, exponent, remainder):
possibleWitness = pow(possibleWitness, remainder, p)
if possibleWitness == 1 or possibleWitness == p - 1:
return False
for _ in range(exponent):
possibleWitness = pow(possibleWitness, 2, p)
if possibleWitness == p - 1:
return False
return True
def probablyPrime(p, accuracy=100):
if p == 2 or p == 3: return True
if p < 2: return False
exponent, remainder = decompose(p - 1)
for _ in range(accuracy):
possibleWitness = random.randint(2, p - 2)
if isWitness(possibleWitness, p, exponent, remainder):
return False
return True
""" Coupon-Collector Problem (approximation)
How many random-samplings with replacement are expected to observe each element at least once
"""
def couponcollector(n):
return int(n*math.log(n))
""" Non-prime random-sampling
"""
def get_random_nonprime(min, max):
max_trials = couponcollector(max-min)
for i in range(max_trials):
candidate = random.randint(min, max)
if not probablyPrime(candidate):
return candidate
return -1
# TEST
print(get_random_nonprime(1000, 10000000))