先说结论
判断一个数n是否为质数(素数)时,只需要判断小于或等于sqrt(n)的数能否整除n即可。这是因为如果n是一个合数,那么n可以分解为a和b两个数,即n = a ✖️ b,那么这两个因数中必然有一个小于或等于sqrt(n),另一个大于或等于sqrt(n)。因此只需要找出小于或等于sqrt(n)的因数,既可以判断n是否为合数。这样大大减少了需要检测的除数数量,提高了效率。
具体解释
- 合数的性质:如果一个大于1的整数
n不是质数,那么它就是合数,并且一定存在其他的因子,除了1和它本身。 - 因数成对出现:假设
n是一个合数,我们可以将其分解成两个因子a和b,使得n = a ✖️ b。 - 平方根的意义:
- 如果
a=b,那么pow(a,2) = n,意味着sqrt(n) = a,所以a和b都等于sqrt(n)。 - 如果
a≠b,那么必然有一个因子小于sqrt(n),另一个因子大于sqrt(n)。如果两个因数都大于sqrt(n),那它们的乘积一定大于n,反之则一定小于n。
- 如果
- 效率提升:由于合数一定有一个因子小于或等于其平方根,那么当我们从2开始检查到
sqrt(n)之间的所有整数时,如果能找到一个因子能够整除n,那么n就是合数,如果在这个范围内都没有找到任何因子能够整除n,那么n就一定是质数。
private bool CheckPrimeNumber(int number)
{
if (number <= 1)
{
throw new ArgumentOutOfRangeException();
}
var sqrt = Math.Sqrt(number);
for (var current = 2; current <= sqrt; current++)
{
if (number % current == 0)
{
return false;
}
}
return true;
}
其他方法
根据质数的性质,在整数n > 2的情况下,需要检查n能不能被2 ~ (n-1)这个区间内的数整除,而在大于n/2时无论其取何值,都不可能使n被整除,所以只要判断2 ~ n/2之间的数是否能整除n即可。
private bool CheckPrimeNumber(int number)
{
if (number <= 1)
{
throw new ArgumentOutOfRangeException();
}
var middle = number / 2;
for (var current = 2; current <= middle; current++)
{
if (number % current == 0)
{
return false;
}
}
return true;
}