先说结论
判断一个数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;
}