【发布时间】:2011-08-14 05:54:38
【问题描述】:
要测试一个数是否是素数,为什么我们必须测试它是否只能被该数的平方根整除?
【问题讨论】:
-
因为如果
n = a*b和a <= b然后a*a <= a*b = n。 -
澄清一下,这意味着我们只需要测试到
floor(sqrt(n))。
标签: algorithm primes primality-test
要测试一个数是否是素数,为什么我们必须测试它是否只能被该数的平方根整除?
【问题讨论】:
n = a*b 和a <= b 然后a*a <= a*b = n。
floor(sqrt(n))。
标签: algorithm primes primality-test
设 n 为非质数。因此,它至少有两个大于 1 的整数因子。设 f 是 n 的这些因子中的最小值。假设 f > sqrt n。那么 n/f 是一个整数 ≤ sqrt n,因此小于 f。因此,f 不可能是 n 的最小因子。减少荒谬; n 的最小因数必须≤ sqrt n。
【讨论】:
是的,正如上面正确解释的那样,迭代到 Math.floor 一个数字的平方根来检查它的素数就足够了(因为sqrt 涵盖了所有可能的除法情况;Math.floor,因为任何整数以上sqrt 已经超出了它的范围)。
这是一个可运行的 JavaScript 代码 sn-p,它代表了这种方法的一个简单实现——它的“运行时友好性”足以处理相当大的数字(我尝试检查素数和不是最高 10**12 的素数,即 1 万亿,将结果与online database of prime numbers 进行比较,即使在我的廉价手机上也没有遇到错误或滞后):
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不是素数,它可以分解为两个因式a和b:
n = a * b
现在a 和b 不能都大于n 的平方根,从那时起乘积a * b 将大于sqrt(n) * sqrt(n) = n。所以在n的任何因式分解中,至少有一个因式必须小于n的平方根,如果找不到任何小于或等于平方根的因式,n必须是一个素数。
【讨论】:
sqrt(n) 如何必须足够精确才能保持该属性。
i * i <= n 而不是 i <= sqrt(n)。
i <= n / i 可能没有这个问题。
假设我们有一个数字“a”,它不是素数[不是素数/复合数意味着 - 一个可以被除 1 或它本身以外的数字整除的数字。例如,6 可以除以 2,或除以 3,也可以除以 1 或 6]。
6 = 1 × 6 或 6 = 2 × 3
所以现在如果“a”不是素数,那么它可以除以另外两个数字,假设这些数字是“b”和“c”。这意味着
a=b*c。
现在如果 "b" 或 "c" ,它们中的任何一个都大于 "a" 的平方根,而不是 "b" 和 "c" 的乘积将大于 "a"。
因此,“b”或“c”总是
由于上述原因,当我们测试一个数是否为素数时,我们只检查直到该数的平方根。
【讨论】:
给定任意数n,那么求其因数的一种方法是求其平方根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 的整个范围。另一个p 是镜像副本,因此实际上我们将范围减半。然后,现在我看到我们实际上可以继续重新执行 square root 并将其执行到 p 以进一步扩大一半范围。
【讨论】:
假设m = sqrt(n) 然后m × m = n。现在如果n 不是素数,那么n 可以写成n = a × b,所以m × m = a × b。请注意,m 是实数,而 n、a 和 b 是自然数。
现在可能有3种情况:
在所有 3 种情况下,min(a, b) ≤ m。因此,如果我们搜索到m,我们肯定会找到n 的至少一个因子,这足以证明n 不是素数。
【讨论】:
n is not a prime,并证明它,否则它是素数。
a 和 b 都不能大于 sqrt(n)。 3 个案例让我明白了。
任何合数都是素数的乘积。
假设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) 总是正确的。
【讨论】:
假设给定的整数 N 不是素数,
然后 N 可以分解为两个因子 a 和 b , 2 <= a, b < N 使得 N = a*b。
显然,它们不能同时大于sqrt(N)。
让我们不失一般性地假设a 更小。
现在,如果您在[2, sqrt(N)] 范围内找不到任何N 的除数,那是什么意思?
这意味着N 在[2, a] 中没有任何除数作为a <= sqrt(N)。
因此,a = 1 和 b = n,因此 根据定义,N 是素数。
...
如果您不满意,请继续阅读:
(a, b) 的许多不同组合都是可能的。假设他们是:
(a1, b1), (a2, b2), (a3, b3), ..... , (ak, bk)。不失一般性,假设 aii, 1<= i <=k.
现在,为了能够证明N 不是质数,证明没有任何一个i 可以被进一步分解就足够了。而且我们还知道 aisqrt(N),因此您需要检查直到 sqrt(N),这将涵盖所有 ai。因此,您将能够得出N 是否为素数的结论。
...
【讨论】:
要测试一个数字的素数,n,首先需要一个循环,如下所示:
bool isPrime = true;
for(int i = 2; i < n; i++){
if(n%i == 0){
isPrime = false;
break;
}
}
上述循环的作用是:对于给定的 1 ,它检查 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 (integer)
或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) (其中两个检查减少为一个)即 a = k ,此时 a*a = n,意味着 a = sqrt(n)。
换句话说,如果对于某些 i >= sqrt(n)(即 max(a,k)),n 的素性检验失败,那么对于某些 i
【讨论】:
所以要检查一个数 N 是否是素数。 我们只需要检查 N 是否可以被数字整除Y N
因此一个因子必须小于或等于 SQROOT(N) (而另一个因子大于或等于 SQROOT(N) )。 因此,要检查 N 是否为素数,我们只需要检查这些数字
【讨论】:
这只是因式分解和平方根的基本用途。
它可能看起来很抽象,但实际上它只是在于非质数的最大可能阶乘必须是它的平方根,因为:
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;
}
【讨论】:
guard 语句以及这个方便的 stackoverflow.com/a/25555762/4475605 来提前退出计算而不是浪费计算能力。感谢您发帖。
++i 将成为数字 1,这将始终返回 false(因为 1 可以除以一切)。我已经更正了上面的答案。
假设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)不是质数,并且我们测试该数的平方根的可除性,我们会找到其中一个因数。
【讨论】:
因为如果一个因子大于 n 的平方根,那么与它相乘等于 n 的另一个因子必然小于 n 的平方根。
【讨论】: