可能な除数の範囲内の素数のみをチェックする必要があります。たとえば、値が 2 で割り切れない場合、2 の倍数でも割り切れません。他のすべての素数と素数倍数についても同様です。したがって、あなたの例ではチェックできます2, 3, 5
-チェックする必要はありません4
。4で割り切れるものは2で割り切れる必要があるためです。したがって、より高速なアプローチは、関心のある範囲で素数を計算し、次に単純にそれらが分割する値。
別のスピードアップは、関心のある範囲内の各値を a に追加することですset
。範囲内の数値で割り切れる場合は、セットから削除します。次に、セットに残っている数字のみをテストする必要があります。これにより、数字を複数回テストすることがなくなります。
これら 2 つのアプローチを組み合わせるとset
、すべての値 (例では、すべての値が 1 から 10 のセット) を作成し、そのセットから 2 番目の範囲の各素数の倍数を単純に削除できることがわかります。
編集: パタシュが指摘したように、特定の値を分割する素数がセットにない場合、これはうまく機能しません。これを修正するには、上記と同様のアルゴリズムを適用できます: 値を持つ を作成しset
、[a, b]
の各値に対して、set
その倍数をすべて削除します。したがって、以下のコメント ( with [3, 6]
) の例では、3 から始めて、セット内の倍数を削除します - so 6
。したがって、テストする必要がある残りの値は[3, 4, 5]
、この場合に必要なものです。
Edit2:これは、最適化されておらず、恐ろしい変数名を持つ、本当にハッキングされた、くだらない実装です:
def find_non_factors():
a = 1
b = 1000000
x = 200
y = 1000
z = [True for p in range(x, y+1)]
for k, i in enumerate(z):
if i:
k += x
n = 2
while n * k < y + 1:
z[(n*k) - x] = False
n += 1
k = {p for p in range(a, b+1)}
for p, v in enumerate(z):
if v:
t = p + x
n = 1
while n * t < (b + 1):
if (n * t) in k:
k.remove(n * t)
n += 1
return k
これらの数値で元の実装を試してください。私のコンピューターでは 1 分以上かかります。この実装には 2 秒もかかりません。