用NumPy生成孪生素数:如何更简洁地翻转True后的False值?
NumPy生成孪生素数的掩码优化方案
我想用NumPy生成孪生素数(差值为2的两个素数),思路是先用埃拉托斯特尼筛法生成素数数组,再筛选出差值为2的相邻素数。
目前我实现的筛选逻辑如下:
import numpy as np def twin_primes(n: int) -> np.ndarray: primes = prime_wheel_sieve(n) # 假设prime_wheel_sieve是已实现的筛法函数 mask = np.isin(primes + 2, primes) mask |= np.concatenate([[False], mask])[:-1] return primes[mask]
预期输出(以n=1000为例):
In [367]: twin_primes(1000) Out[367]: array([ 3, 5, 7, 11, 13, 17, 19, 29, 31, 41, 43, 59, 61, 71, 73, 101, 103, 107, 109, 137, 139, 149, 151, 179, 181, 191, 193, 197, 199, 227, 229, 239, 241, 269, 271, 281, 283, 311, 313, 347, 349, 419, 421, 431, 433, 461, 463, 521, 523, 569, 571, 599, 601, 617, 619, 641, 643, 659, 661, 809, 811, 821, 823, 827, 829, 857, 859, 881, 883], dtype=int64)
原逻辑中,np.isin(primes + 2, primes)能找到所有孪生素数对的第一个数(比如3、5),但没法覆盖第二个数(比如5、7)。本质是要把掩码中每个True后面的False也转为True,我现在用掩码右移后取或的方式解决,但想知道有没有更简洁的实现方式。
几种更简洁的实现方法
方法1:简化掩码移位写法
原逻辑的移位操作可以简化为直接截取掩码前n-1位补False开头,写法更直观:
mask = np.isin(primes + 2, primes) # 右移一位,开头补False,避免循环移位的误判 mask |= np.concatenate([[False], mask[:-1]])
方法2:利用素数差值直接生成掩码
既然孪生素数对的相邻素数差值为2,直接计算差值后生成掩码,逻辑更清晰且效率更高:
# 计算相邻素数的差值 prime_diff = np.diff(primes) # 初始化全False的掩码 mask = np.zeros_like(primes, dtype=bool) # 差值为2的位置,对应当前素数和下一个素数都是孪生素数 mask[:-1][prime_diff == 2] = True mask[1:][prime_diff == 2] = True
方法3:一行式掩码生成
结合差值判断和索引合并,用更紧凑的写法生成掩码:
diff_indices = np.where(np.diff(primes) == 2)[0] mask = np.zeros(len(primes), dtype=bool) mask[np.r_[diff_indices, diff_indices + 1]] = True
内容的提问来源于stack exchange,提问作者Ξένη Γήινος
相关产品推荐
相关产品推荐

