数が素数であるかどうかをテストするには、なぜその数の平方根までしか除算できないかどうかをテストする必要があるのでしょうか。
13 に答える
数が素数でない場合、それは2つの要因にn
因数分解することができます:a
b
n = a * b
現在a
、およびb
の両方をの平方根より大きくすることはできません。n
それ以降、積a * b
は。より大きくなりsqrt(n) * sqrt(n) = n
ます。したがって、の因数分解ではn
、少なくとも1つの因数がの平方根よりも小さい必要があります。n
平方根以下の因数が見つからない場合はn
、素数である必要があります。
m = sqrt(n)
それでは、としましょうm × m = n
。n
が素数でない場合は、n
と書くことができます。は実数であるのに対し、、は自然数であることに注意してください。n = a × b
m × m = a × b
m
n
a
b
現在、3つのケースが考えられます。
- a>m⇒b<m
- a=m⇒b=m
- a<m⇒b>m
3つのケースすべてで、min(a, b) ≤ m
。したがって、まで検索するm
と、の少なくとも1つの因子が見つかるはずです。これは、素数n
ではないことを示すのに十分です。n
因子がnの平方根よりも大きい場合、nに等しくなるようにそれを乗算する他の因子は、必然的にnの平方根よりも小さくなるためです。
素数n
(1より大きい)ではないとします。だから数字などがa
ありb
ます
n = ab (1 < a <= b < n)
a<=b
関係にを掛けるa
と、次のb
ようになります。
a^2 <= ab
ab <= b^2
したがって:(注意してくださいn=ab
)
a^2 <= n <= b^2
したがって:(a
とb
は正であることに注意してください)
a <= sqrt(n) <= b
したがって、数(1より大きい)が素数ではなく、数の平方根までの除算性をテストする場合、要因の1つが見つかります。
それはすべて、因数分解と平方根の基本的な使用法です。
抽象的に見えるかもしれませんが、実際には、非素数の可能な最大階乗は、次の理由で平方根でなければならないという事実に基づいています。
sqrroot(n) * sqrroot(n) = n
。
1
とすると、上下または最大の整数sqrroot(n)
が均等にに分割される場合、素数にすることはできませんn
。n
擬似コードの例:
i = 2;
is_prime = true;
while loop (i <= sqrroot(n))
{
if (n % i == 0)
{
is_prime = false;
exit while;
}
++i;
}
N
与えられた整数が素数ではないと仮定しましょう、
次に、Nは2つの因子a
とb
に 因数分解できます。明らかに、両方を同時に大きくすることはできません。2 <= a, b < N
N = a*b
sqrt(N)
一般性を失うことなく、より小さなものを想定しましょうa
。
N
さて、範囲内に属する除数が見つからなかった場合、[2, sqrt(N)]
それはどういう意味ですか?
これは、としてN
除数がないことを意味します。[2, a]
a <= sqrt(N)
したがって、したがって、したがって、a = 1
定義b = n
上、N
は素数です。
..。
満足できない場合は、さらに読んでください。
多くの異なる組み合わせが(a, b)
可能かもしれません。彼らがそうだとしましょう:
(a 1、b 1)、(a 2、b 2)、(a 3、b 3)、.....、(a k、b k)。一般性を失うことなく、a i <b i、と仮定し1<= i <=k
ます。
さて、N
それが素数ではないことを示すことができるためには、iのどれもそれ以上因数分解できないことを示すことで十分です。また、a i <=であることがわかっているため、すべてのaiをカバーsqrt(N)
するまでチェックする必要があります。したがって、プライムであるかどうかを結論付けることができます。sqrt(N)
N
..。
素数ではない数「a」があるとしましょう[素数/合成数ではないということは、1またはそれ自体以外の数で均等に割ることができる数を意味します。たとえば、6は2、3、および1または6で均等に分割できます]。
6=1×6または6=2×3
したがって、「a」が素数でない場合は、他の2つの数で割ることができ、それらの数が「b」と「c」であるとしましょう。つまり、
a = b*c。
ここで、「b」または「c」の場合、それらのいずれかが「a」の平方根よりも大きく、「b」と「c」の乗算よりも「a」よりも大きくなります。
したがって、方程式「a = b * c」を証明するために、「b」または「c」は常に「a」の平方根未満です。
上記の理由により、数値が素数であるかどうかをテストする場合、その数値の平方根までのみチェックします。
したがって、数値Nが素数であるかどうかを確認します。Nがnumbers<=SQROOT(N)で割り切れるかどうかを確認するだけで済みます。これは、Nを任意の2つの要素に因数分解すると、XとY、つまり、N = XY。XとYのそれぞれはSQROOT(N)より小さくすることはできません。その場合、X Y <N XとYのそれぞれはSQROOT(N)より大きくなることはできません。その場合、X * Y> N
したがって、一方の係数はSQROOT(N)以下である必要があります(もう一方の係数はSQROOT(N)以上である必要があります)。したがって、Nが素数であるかどうかを確認するには、これらの数値<= SQROOT(N)のみを確認する必要があります。
nを非プライムとします。したがって、1より大きい少なくとも2つの整数因子があります。fをnのそのような因子の最小値とします。f>sqrtnと仮定します。その場合、n / fは整数≤sqrtnであるため、fよりも小さくなります。したがって、fをnの最小係数にすることはできません。帰謬法; nの最小係数は≤sqrtnでなければなりません。
任意の数が与えられた場合n
、その因子を見つける1つの方法は、その平方根を取得することp
です。
sqrt(n) = p
もちろん、p
それ自体で乗算すると、元に戻りますn
:
p*p = n
次のように書き直すことができます。
a*b = n
どこp = a = b
。a
増加する場合は、b
減少して維持しa*b = n
ます。したがって、p
が上限です。
更新:私は今日この答えをもう一度読み直しており、それは私にとってより明確になりました。整数を意味する場合、素数ではないため、値p
は必ずしも整数を意味するわけではありませんn
。したがって、p
実数(つまり、分数)である可能性があります。そして、の全範囲を通過する代わりにn
、今では、の全範囲を通過するだけで済みp
ます。もう1つp
はミラーコピーであるため、実際には範囲が半分になります。そして今、私たちは実際にやり直しを続けて、範囲のさらに半分まで square root
それを行うことができることを確認しています。p
合成数は素数の積です。
としましょうn = p1 * p2
、どこでp2 > p1
、それらは素数です。
その場合n % p1 === 0
、nは合成数です。
それならn % p2 === 0
、何も推測しn % p1 === 0
てください!
n % p2 === 0
ですから、それn % p1 !== 0
を同時に行う方法はありません。言い換えると、合成数nをp2、p3 ... pi (より大きな係数)で均等に除算できる
場合は、最小の係数p1でも除算する必要があります。最も低い要因p1 <= Math.square(n)
は常に真であることがわかります。
はい、上で適切に説明したように、数の平方根のMath.floorまで反復して、その素数性をチェックするだけで十分です(sqrt
除算のすべての可能なケースをカバーするMath.floor
ため、および、上記の整数sqrt
はすでにその範囲を超えているため)。
これは、このアプローチの単純な実装を表す実行可能なJavaScriptコードスニペットです。その「実行時の使いやすさ」は、かなり大きな数を処理するのに十分です(10 ** 12までの素数と素数ではない両方をチェックしてみました。つまり、1兆、素数のオンラインデータベースと結果を比較し、私の安い電話でもエラーやラグは発生しませんでした):
function isPrime(num) {
if (num % 2 === 0 || num < 3 || !Number.isSafeInteger(num)) {
return num === 2;
} else {
const sqrt = Math.floor(Math.sqrt(num));
for (let i = 3; i <= sqrt; i += 2) {
if (num % i === 0) return false;
}
return true;
}
}
<label for="inp">Enter a number and click "Check!":</label><br>
<input type="number" id="inp"></input>
<button onclick="alert(isPrime(+document.getElementById('inp').value) ? 'Prime' : 'Not prime')" type="button">Check!</button>
数nの素数性をテストするには、最初に次のようなループが必要です。
bool isPrime = true;
for(int i = 2; i < n; i++){
if(n%i == 0){
isPrime = false;
break;
}
}
上記のループは次のようになります。指定された1<i<nに対して、n / iが整数であるかどうかをチェックします(余りは0のままにします)。n / iが整数であるiが存在する場合、nが素数ではないことを確認でき、その時点でループが終了します。iがない場合、n / iは整数であり、nは素数です。
すべてのアルゴリズムと同様に、次のように質問します。
上記のループで何が起こっているかを見てみましょう。
iのシーケンスは次のようになります:i = 2、3、4、...、n-1
そして、整数チェックのシーケンスは次のようになります:j = n / i、つまりn / 2、n / 3、n / 4、...、n /(n-1)
一部のi=aの場合、n / aは整数であり、n / a = k(整数)
またはn=ak、明らかにn> k> 1(k = 1の場合、a = nですが、iはnに到達しません。k= nの場合、a = 1ですが、iは2から始まります)
また、n / k = aであり、前述のように、aはiの値であるため、n>a>1です。
したがって、aとkは両方とも1からnまでの整数(排他的)です。以来、iはその範囲内のすべての整数に到達するため、ある反復ではi = aであり、他の反復ではi=kです。nの素数性テストがmin(a、k)で失敗した場合、max(a、k)でも失敗します。したがって、min(a、k)= max(a、k)(2つのチェックが1つに減る)、つまりa = k、その時点でa * a = nでない限り、これら2つのケースの1つだけをチェックする必要があります。 a = sqrt(n)を意味します。
言い換えると、nの素数性テストがi> = sqrt(n)(つまり、max(a、k))で失敗した場合、i <= n(つまり、min(a)でも失敗します。 、k))。したがって、i = 2からsqrt(n)のテストを実行すれば十分です。