当您使用最后一个值(curr)来确定下一个范围时,您正在指数级地增加范围。平均而言,随机质数应该落在范围的中间,并且范围从X到2X。这将使每次迭代将范围向前移动大约1.5X的因素。通过10,000次迭代,您的范围将增加高达1.5 ^ 10000(2 ^ 5850)的因素,这很快将使即使sympy也很难产生质数。
如果您的目标仅是在第i个和(i + 1)个质数之间具有足够数量的不同位,那么您可以保持相同数量级,并在先前的质数上过滤出最少数量的不同位(而不是增加随机范围的数量级)。
例如:
def oneBits(N): return N%2 + oneBits(N//2) if N else 0
minDiff = 25
minValue = 2**50
maxValue = minValue*2-1
primes = [randprime(minValue,maxValue)]
count = 10000
for _ in range(count-1):
while True:
p = randprime(minValue,maxValue)
if oneBits(primes[-1]^p)>=minDiff: break
primes.append(p)
请注意,我没有安装sympy,因此我使用纯随机数进行了不同的测试,以获取下一个质数:
内存高效的质数生成器:
def genPrimes(toN):
skips = dict()
maxSkip = int(toN**0.5)
if toN>=2: yield 2
for p in range(3,toN+1,2):
if p not in skips:
yield p
if p <= maxSkip: skips[p*p] = 2*p
else:
stride = skips.pop(p)
multiple = p + stride
while multiple in skips: multiple += stride
skips[multiple] = stride
获取从N开始的下一个质数的函数:
primes = list(genPrimes(2**26))
def nextPrime(N):
sieve = [1]*N.bit_length()*20
maxPrime = int((N+len(sieve))**0.5)
for p in primes:
if p>maxPrime: break
offset = (p-N%p)%p
if offset>len(sieve): continue
sieve[offset::p] = [0]*len(range(offset,len(sieve),p))
for p,isPrime in enumerate(sieve,N):
if isPrime: return p
return nextPrime(N+len(sieve))
最小间隔50位质数(生成器):
import random
def randomPrimes(count,bits=50):
minVal = 2**bits
maxVal = minVal*2-1
minDiff = bits//2
prevPrime = 0
def oneBits(N): return N%2 + oneBits(N//2) if N else 0
for _ in range(count):
while True:
n = random.randint(minVal,maxVal)
if prevPrime and oneBits(prevPrime^n)<minDiff: continue
n = nextPrime(n)
if not prevPrime: break
if oneBits(prevPrime^n)>=minDiff: break
yield n
输出:
for p in randomPrimes(10000):
print(p,f"{p:b}")
2071968049418461 111010111000111000110100111100100100101000011011101
1399795190350597 100111110010001101100110111000101000100001100000101
1530818178259709 101011100000100010101100001101110110001101011111101
1140103670657957 100000011001110101100010010010010111111001110100101
1911908333932859 110110010101101111011011001000101100101000100111011
1236033889571977 100011001000010101010010000111010110001010010001001
1752989992684999 110001110100101010111001001110011110000110111000111
1849449158362859 110100100100001000001110000000111010100011011101011
1349704431776567 100110010111000110010001101001101010011001100110111
1142235147712271 100000011101101101101011000001110101011011100001111
...
这大约需要0.5秒钟来完成每一次迭代(无论迭代次数多少)。我相信sympy应该比我自己编写的函数要快得多。
randprime
需要转换为整数)。如果这对你来说太慢了,你可能需要完全改变方法。话虽如此,你所尝试做的事情本质上很慢,因为这不是一项容易的任务。 - Ma0