私が探しているもののほんの一例:私はすべての奇数を少しで表すことができます指定された範囲の番号(1、10]に対して、3から始まります:
1110
次の辞書をより適切に絞り込めますか?いくつかの作業で5の倍数を排除できますが、ビット配列には1、3、7、または9で終わる数字がなければなりません。これが私が望むものを明確にすることを願っています。
私は、数値が素数であるかどうか、つまりブール関数かどうかを確認するための最良のアルゴリズムを探しています:
bool isprime(number);
この機能を実装するのに最適なアルゴリズムを知りたいです。当然、クエリできるデータ構造があります。 I 最適なアルゴリズムの定義、範囲(1、N]でメモリ消費量が最小のデータ構造を生成するアルゴリズムになります。Nは定数です。
primality test を行うには多くの方法があります。
クエリを実行するためのデータ構造は実際にはありません。テストする数字がたくさんある場合は、おそらくより高速なので 確率的テスト を実行し、その後に 決定論的テスト を実行して数字が正しいことを確認する必要があります。プライム。
最速のアルゴリズムの背後にある数学は、気弱な人向けではないことを知っておく必要があります。
一般的な素数テストの最速のアルゴリズムは AKS です。ウィキペディアの記事には、長さおよび元の論文へのリンクが記載されています。
大きな数を見つけたい場合は、 Mersenne primes のような特別な形式の素数を調べてください。
私が通常実装するアルゴリズム(理解しやすく、コーディングしやすい)は次のとおりです(Pythonの場合):
def isprime(n):
"""Returns True if n is prime."""
if n == 2:
return True
if n == 3:
return True
if n % 2 == 0:
return False
if n % 3 == 0:
return False
i = 5
w = 2
while i * i <= n:
if n % i == 0:
return False
i += w
w = 6 - w
return True
これは、古典的なO(sqrt(N))
アルゴリズムのバリアントです。プライム(2と3を除く)の形式は6k - 1
または6k + 1
であり、この形式の約数のみを調べるという事実を使用します。
時々、本当に速度が必要で、範囲が制限されている場合、 Fermatの小さな定理 に基づいて擬似プライムテストを実装します。もっと高速にしたい場合(つまり、O(sqrt(N))アルゴリズムを完全に回避する場合)、偽陽性を事前計算し( Carmichael 数値を参照)、バイナリ検索を実行します。これは私がこれまで実装した中で最も速いテストであり、唯一の欠点は範囲が限られていることです。
私の意見では、最善の方法は以前に行ったことを使用することです。
インターネット上に最初のN
素数のリストがあり、N
が少なくとも 5000万 まで伸びています。ファイルをダウンロードして使用すると、他の方法よりもはるかに高速になる可能性があります。
独自の素数を作成するための実際のアルゴリズムが必要な場合、ウィキペディアには素数に関するあらゆる種類の優れたものがあります here (これを行うためのさまざまな方法へのリンク、および素数テスト here =、確率ベースおよび高速決定論的手法の両方。
最初の10億(またはそれ以上)の素数を見つけて、どこかでネット上に公開して、人々がこの同じ仕事を何度も何度もやめられるようにするための協調的な努力が必要です... :-)
bool isPrime(int n)
{
// Corner cases
if (n <= 1) return false;
if (n <= 3) return true;
// This is checked so that we can skip
// middle five numbers in below loop
if (n%2 == 0 || n%3 == 0) return false;
for (int i=5; i*i<=n; i=i+6)
if (n%i == 0 || n%(i+2) == 0)
return false;
return true;
}
this is just c++ implementation of above AKS algorithm
Python 3:で
def is_prime(a):
if a < 2:
return False
Elif a!=2 and a % 2 == 0:
return False
else:
return all (a % i for i in range(3, int(a**0.5)+1))
説明:素数は、それ自身と1でのみ割り切れる数です。例:2,3,5,7 ...
1)a <2:の場合 "a"が2未満の場合、素数ではありません。
2)Elif a!= 2 and a%2 == 0: "a"が2で割り切れる場合、それは間違いなく素数ではありません。ただし、a = 2の場合、それは素数であるため評価したくありません。したがって、条件a!= 2
)すべてを返します(range(3、int(a 0.5)+1のiの%i)):**まず、pythonでall()コマンドが何をするかを見てください。 3から始めて、「a」をその平方根(a ** 0.5)まで分割します。 「a」が割り切れる場合、出力はFalseになります。なぜ平方根なのか? a = 16としましょう。 16 = 4の平方根。15まで評価する必要はありません。それが素数でないことを示すために4までチェックするだけです。
Extra:範囲内のすべての素数を見つけるためのループ。
for i in range(1,100):
if is_prime(i):
print("{} is a prime number".format(i))
ウィキペディアによると、 the Sieve of Eratosthenes has complexity O(n * (log n) * (log log n))
and require O(n)
memory -したがって、特に大きな数をテストしない場合は、開始するのに適した場所です。
sympyを使用できます。
import sympy
sympy.ntheory.primetest.isprime(33393939393929292929292911111111)
True
sympy docsから。最初のステップは、些細な要因を探すことです。それが見つかれば、すぐに戻ります。次に、ふるいが十分に大きい場合、ふるいで二分探索を使用します。少数の場合、範囲内に反例がないことが知られている基底を使用して、決定論的なミラーラビンテストのセットが実行されます。最後に、数値が2 ^ 64より大きい場合、強力なBPSWテストが実行されます。これはありそうな素数テストであり、反例が存在すると信じていますが、既知の反例はありません
最も人気のある提案の効率を比較して、数値が素数であるかどうかを判断しました。 python 3.6
でubuntu 17.10
を使用しました。最大100.000の数字でテストしました(以下のコードを使用して、より大きな数字でテストできます)。
この最初のプロットは関数(これは私の答えでさらに説明します)を比較し、最後の関数が数値を増やしたときに最初の関数ほど速く成長しないことを示しています。
そして、2番目のプロットでは、素数の場合、時間は着実に増加しますが、非素数はそれほど速く成長しません(それらのほとんどは早期に除去できるため)。
私が使用した関数は次のとおりです。
この答え および この答え は、all()
を使用する構成を提案しました。
def is_prime_1(n):
return n > 1 and all(n % i for i in range(2, int(math.sqrt(n)) + 1))
この回答 何らかのwhileループを使用しました:
def is_prime_2(n):
if n <= 1:
return False
if n == 2:
return True
if n == 3:
return True
if n % 2 == 0:
return False
if n % 3 == 0:
return False
i = 5
w = 2
while i * i <= n:
if n % i == 0:
return False
i += w
w = 6 - w
return True
この回答for
ループのあるバージョンが含まれています:
def is_prime_3(n):
if n <= 1:
return False
if n % 2 == 0 and n > 2:
return False
for i in range(3, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
そして、他の回答からのいくつかのアイデアを新しいものに混ぜました:
def is_prime_4(n):
if n <= 1: # negative numbers, 0 or 1
return False
if n <= 3: # 2 and 3
return True
if n % 2 == 0 or n % 3 == 0:
return False
for i in range(5, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
バリアントを比較するスクリプトは次のとおりです。
import math
import pandas as pd
import seaborn as sns
import time
from matplotlib import pyplot as plt
def is_prime_1(n):
...
def is_prime_2(n):
...
def is_prime_3(n):
...
def is_prime_4(n):
...
default_func_list = (is_prime_1, is_prime_2, is_prime_3, is_prime_4)
def assert_equal_results(func_list=default_func_list, n):
for i in range(-2, n):
r_list = [f(i) for f in func_list]
if not all(r == r_list[0] for r in r_list):
print(i, r_list)
raise ValueError
print('all functions return the same results for integers up to {}'.format(n))
def compare_functions(func_list=default_func_list, n):
result_list = []
n_measurements = 3
for f in func_list:
for i in range(1, n + 1):
ret_list = []
t_sum = 0
for _ in range(n_measurements):
t_start = time.perf_counter()
is_prime = f(i)
t_end = time.perf_counter()
ret_list.append(is_prime)
t_sum += (t_end - t_start)
is_prime = ret_list[0]
assert all(ret == is_prime for ret in ret_list)
result_list.append((f.__name__, i, is_prime, t_sum / n_measurements))
df = pd.DataFrame(
data=result_list,
columns=['f', 'number', 'is_prime', 't_seconds'])
df['t_micro_seconds'] = df['t_seconds'].map(lambda x: round(x * 10**6, 2))
print('df.shape:', df.shape)
print()
print('', '-' * 41)
print('| {:11s} | {:11s} | {:11s} |'.format(
'is_prime', 'count', 'percent'))
df_sub1 = df[df['f'] == 'is_prime_1']
print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
'all', df_sub1.shape[0], 100))
for (is_prime, count) in df_sub1['is_prime'].value_counts().iteritems():
print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
str(is_prime), count, count * 100 / df_sub1.shape[0]))
print('', '-' * 41)
print()
print('', '-' * 69)
print('| {:11s} | {:11s} | {:11s} | {:11s} | {:11s} |'.format(
'f', 'is_prime', 't min (us)', 't mean (us)', 't max (us)'))
for f, df_sub1 in df.groupby(['f', ]):
col = df_sub1['t_micro_seconds']
print('|{0}|{0}|{0}|{0}|{0}|'.format('-' * 13))
print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
f, 'all', col.min(), col.mean(), col.max()))
for is_prime, df_sub2 in df_sub1.groupby(['is_prime', ]):
col = df_sub2['t_micro_seconds']
print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
f, str(is_prime), col.min(), col.mean(), col.max()))
print('', '-' * 69)
return df
関数compare_functions(n=10**5)
(100.000までの番号)を実行すると、次の出力が得られます。
df.shape: (400000, 5)
-----------------------------------------
| is_prime | count | percent |
| all | 100,000 | 100.0 % |
| False | 90,408 | 90.4 % |
| True | 9,592 | 9.6 % |
-----------------------------------------
---------------------------------------------------------------------
| f | is_prime | t min (us) | t mean (us) | t max (us) |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1 | all | 0.57 | 2.50 | 154.35 |
| is_prime_1 | False | 0.57 | 1.52 | 154.35 |
| is_prime_1 | True | 0.89 | 11.66 | 55.54 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2 | all | 0.24 | 1.14 | 304.82 |
| is_prime_2 | False | 0.24 | 0.56 | 304.82 |
| is_prime_2 | True | 0.25 | 6.67 | 48.49 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3 | all | 0.20 | 0.95 | 50.99 |
| is_prime_3 | False | 0.20 | 0.60 | 40.62 |
| is_prime_3 | True | 0.58 | 4.22 | 50.99 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4 | all | 0.20 | 0.89 | 20.09 |
| is_prime_4 | False | 0.21 | 0.53 | 14.63 |
| is_prime_4 | True | 0.20 | 4.27 | 20.09 |
---------------------------------------------------------------------
次に、関数compare_functions(n=10**6)
(1.000.000までの番号)を実行すると、次の出力が得られます。
df.shape: (4000000, 5)
-----------------------------------------
| is_prime | count | percent |
| all | 1,000,000 | 100.0 % |
| False | 921,502 | 92.2 % |
| True | 78,498 | 7.8 % |
-----------------------------------------
---------------------------------------------------------------------
| f | is_prime | t min (us) | t mean (us) | t max (us) |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1 | all | 0.51 | 5.39 | 1414.87 |
| is_prime_1 | False | 0.51 | 2.19 | 413.42 |
| is_prime_1 | True | 0.87 | 42.98 | 1414.87 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2 | all | 0.24 | 2.65 | 612.69 |
| is_prime_2 | False | 0.24 | 0.89 | 322.81 |
| is_prime_2 | True | 0.24 | 23.27 | 612.69 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3 | all | 0.20 | 1.93 | 67.40 |
| is_prime_3 | False | 0.20 | 0.82 | 61.39 |
| is_prime_3 | True | 0.59 | 14.97 | 67.40 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4 | all | 0.18 | 1.88 | 332.13 |
| is_prime_4 | False | 0.20 | 0.74 | 311.94 |
| is_prime_4 | True | 0.18 | 15.23 | 332.13 |
---------------------------------------------------------------------
次のスクリプトを使用して結果をプロットしました。
def plot_1(func_list=default_func_list, n):
df_orig = compare_functions(func_list=func_list, n=n)
df_filtered = df_orig[df_orig['t_micro_seconds'] <= 20]
sns.lmplot(
data=df_filtered, x='number', y='t_micro_seconds',
col='f',
# row='is_prime',
markers='.',
ci=None)
plt.ticklabel_format(style='sci', axis='x', scilimits=(3, 3))
plt.show()
大きな数の場合、候補数Nがsqrt(N)未満の数で割り切れないかどうかを単純に単純にチェックすることはできません。 Miller-Rabin primality test など、はるかにスケーラブルなテストが利用可能です。以下に、Pythonでの実装があります。
def is_prime(x):
"""Fast implementation fo Miller-Rabin primality test, guaranteed to be correct."""
import math
def get_sd(x):
"""Returns (s: int, d: int) for which x = d*2^s """
if not x: return 0, 0
s = 0
while 1:
if x % 2 == 0:
x /= 2
s += 1
else:
return s, x
if x <= 2:
return x == 2
# x - 1 = d*2^s
s, d = get_sd(x - 1)
if not s:
return False # divisible by 2!
log2x = int(math.log(x) / math.log(2)) + 1
# As long as Riemann hypothesis holds true, it is impossible
# that all the numbers below this threshold are strong liars.
# Hence the number is guaranteed to be a prime if no contradiction is found.
threshold = min(x, 2*log2x*log2x+1)
for a in range(2, threshold):
# From Fermat's little theorem if x is a prime then a^(x-1) % x == 1
# Hence the below must hold true if x is indeed a prime:
if pow(a, d, x) != 1:
for r in range(0, s):
if -pow(a, d*2**r, x) % x == 1:
break
else:
# Contradicts Fermat's little theorem, hence not a prime.
return False
# No contradiction found, hence x must be a prime.
return True
これを使用して、巨大な素数を見つけることができます。
x = 10000000000000000000000000000000000000000000000000000000000000000000000000000
for e in range(1000):
if is_prime(x + e):
print('%d is a prime!' % (x + e))
break
# 10000000000000000000000000000000000000000000000000000000000000000000000000133 is a prime!
ランダムな整数をテストする場合、おそらく、Miller-Rabinを呼び出す前に、候補数が1000などの素数で割り切れるかどうかを最初にテストする必要があります。これは、10444344345などの明白な非プライムを除外するのに役立ちます。
パーティーには遅すぎますが、これが役立つことを願っています。これは、大きな素数を探している場合に関係があります。
大きな奇数をテストするには、FermatテストまたはMiller-Rabinテストを使用する必要があります。
これらのテストは、非常に高価なモジュラーべき乗を使用します。n
ビットの累乗には、少なくともn
big int乗算とn
big int除算が必要です。つまり、モジュラーべき乗の複雑さはO(n³)です。
そのため、大きな銃を使用する前に、かなりの数の試行分割を行う必要があります。しかし、単純にそれをしないでください、それらを速くする方法があります。まず、大きな整数に使用する単語に収まる限り多くの素数を乗算します。 32ビットワードを使用する場合、3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 = 3234846615を乗算し、ユークリッドアルゴリズムを使用してテストする数値で最大公約数を計算します。最初のステップの後、数値はワードサイズより小さくなり、完全な整数の除算を実行せずにアルゴリズムを続行します。 GCD!= 1の場合、乗算した素数の1つが数を除算するため、素数ではないという証明が得られます。次に、31 * 37 * 41 * 43 * 47 = 95041567などに進みます。
この方法で数百(または千)素数をテストしたら、40ラウンドのMiller-Rabinテストを実行して数が素数であることを確認できます。40ラウンド後、数が素数であることを確認できます。そうではありません(ハードウェアが誤動作している可能性が高い...)。
Python 3:
def is_prime(a):
return a > 1 and all(a % i for i in range(2, int(a**0.5) + 1))
素数javascriptに最適なアルゴリズム
function isPrime(num) {
if (num <= 1) return false;
else if (num <= 3) return true;
else if (num % 2 == 0 || num % 3 == 0) return false;
var i = 5;
while (i * i <= num) {
if (num % i == 0 || num % (i + 2) == 0) return false;
i += 6;
}
return true
}
Pythonの場合:
def is_prime(n):
return not any(n % p == 0 for p in range(2, int(math.sqrt(n)) + 1))
数学的な形式からPythonへのより直接的な変換ではall(n%p!= 0 ...)を使用しますが、pのすべての値を厳密に評価する必要があります。 True値が見つかった場合、not anyバージョンは早期に終了します。
import math
import time
def check_prime(n):
if n == 1:
return False
if n == 2:
return True
if n % 2 == 0:
return False
from_i = 3
to_i = math.sqrt(n) + 1
for i in range(from_i, int(to_i), 2):
if n % i == 0:
return False
return True
私はここで(2 ^ 61)-1まで機能する素数関数を持っています:
from math import sqrt
def isprime(num): num > 1 and return all(num % x for x in range(2, int(sqrt(num)+1)))
説明:
all()
関数は次のように再定義できます。
def all(variables):
for element in variables:
if not element: return False
return True
all()
関数は、一連のブール値/数値を通過し、0またはFalse
を検出するとFalse
を返します。
sqrt()
関数は、数値の平方根を実行しているだけです。
例えば:
>>> from math import sqrt
>>> sqrt(9)
>>> 3
>>> sqrt(100)
>>> 10
num % x
部分は、num/xのremainderを返します。
最後に、range(2, int(sqrt(num)))
は、2で始まりint(sqrt(num)+1)
で終わるlistを作成することを意味します
範囲の詳細については、こちらをご覧ください website !
num > 1
部分は、変数num
が1よりも大きいかどうかをチェックするだけです。1と0は素数と見なされないためです。
これが役に立てば幸いです:)
素数とは、1とそれ自体で割り切れる任意の数です。他のすべての番号はcompositeと呼ばれます。
素数を見つける最も簡単な方法は、入力数が合成数であるかどうかを確認することです。
function isPrime(number) {
// Check if a number is composite
for (let i = 2; i < number; i++) {
if (number % i === 0) {
return false;
}
}
// Return true for prime numbers
return true;
}
プログラムは、number
の値を1からその値までのすべての整数で除算する必要があります。この数が1つだけでなく、それ自体で均等に分割できる場合、それは複合数です。
変数i
の初期値は、素数と合成数の両方を1で均等に分割できるため、2でなければなりません。
for (let i = 2; i < number; i++)
同じ理由で、i
はnumber
よりも小さくなります。素数と合成数は、それ自体で均等に分割できます。したがって、チェックする理由はありません。
次に、剰余演算子を使用して、変数を均等に分割できるかどうかを確認します。
if (number % i === 0) {
return false;
}
剰余がゼロの場合、number
を均等に分割できることを意味します。したがって、合成数であり、falseを返します。
入力された数値が条件を満たさなかった場合、それは素数であり、関数はtrueを返します。
Java-8ストリームとラムダを使用すると、わずか数行で次のように実装できます。
public static boolean isPrime(int candidate){
int candidateRoot = (int) Math.sqrt( (double) candidate);
return IntStream.range(2,candidateRoot)
.boxed().noneMatch(x -> candidate % x == 0);
}
パフォーマンスはO(sqrt(N))に近いはずです。誰かが役に立つと思うかもしれません。
言及されたAKSアルゴリズムと同様のアイデア
public static boolean isPrime(int n) {
if(n == 2 || n == 3) return true;
if((n & 1 ) == 0 || n % 3 == 0) return false;
int limit = (int)Math.sqrt(n) + 1;
for(int i = 5, w = 2; i <= limit; i += w, w = 6 - w) {
if(n % i == 0) return false;
numChecks++;
}
return true;
}
これが私の答えです。
def isprime(num):
return num <= 3 or (num + 1) % 6 == 0 or (num - 1) % 6 == 0
以下のプロパティのいずれかがTrueの場合、関数はTrueを返します。これらのプロパティは、素数が何であるかを数学的に定義します。
このようなものを試すことができます。
def main():
try:
user_in = int(input("Enter a number to determine whether the number is prime or not: "))
except ValueError:
print()
print("You must enter a number!")
print()
return
list_range = list(range(2,user_in+1))
divisor_list = []
for number in list_range:
if user_in%number==0:
divisor_list.append(number)
if len(divisor_list) < 2:
print(user_in, "is a prime number!")
return
else:
print(user_in, "is not a prime number!")
return
main()
以前の回答のほとんどは正しいですが、ここでは、数が素数であるかどうかをテストするもう1つの方法を示します。復習として、素数は1より大きい整数であり、その要因は1とそれ自体のみです。( source )
解決策:
通常、ループを構築し、番号のテストを開始して、1、2、3で割り切れるかどうかを確認します...テストする番号まで...などですが、チェックする時間を短縮するには、番号を数値は、その値の半分を超えるもので正確に割り切れないため、数値の半分になります。 100を表示したい場合の例は、最大50までループできる素数です。
実際のコード:
def find_prime(number):
if(number ==1):
return False
# we are dividiing and rounding and then adding the remainder to increment !
# to cover not fully divisible value to go up forexample 23 becomes 11
stop=number//2+number%2
#loop through up to the half of the values
for item in range(2,stop):
if number%item==0:
return False
print(number)
return True
if(find_prime(3)):
print("it's a prime number !!")
else:
print("it's not a prime")
#!usr/bin/python3
def prime_check(*args):
for arg in args:
if arg > 1: # prime numbers are greater than 1
for i in range(2,arg): # check for factors
if(arg % i) == 0:
print(arg,"is not Prime")
print(i,"times",arg//i,"is",arg)
break
else:
print(arg,"is Prime")
# if input number is less than
# or equal to 1, it is not prime
else:
print(arg,"is not Prime")
return
# Calling Now
prime_check(*list(range(101))) # This will check all the numbers in range 0 to 100
prime_check(#anynumber) # Put any number while calling it will check.
myInp=int(input("Enter a number: "))
if myInp==1:
print("The number {} is neither a prime not composite no".format(myInp))
Elif myInp>1:
for i in range(2,myInp//2+1):
if myInp%i==0:
print("The Number {} is not a prime no".format(myInp))
print("Because",i,"times",myInp//i,"is",myInp)
break
else:
print("The Number {} is a prime no".format(myInp))
else:
print("Alas the no {} is a not a prime no".format(myInp))
Javaストリームを使用して、O(sqrt(n))でこれを実装できます。 noneMatchは、結果を判断するのに不要であると判断した場合に操作を停止するshortCircuitingメソッドであると考えてください。
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(n == 2 ? "Prime" : IntStream.rangeClosed(2, ((int)(Math.sqrt(n)) + 1)).noneMatch(a -> n % a == 0) ? "Prime" : "Not Prime");