先说结论

判断一个数n是否为质数(素数)时,只需要判断小于或等于sqrt(n)的数能否整除n即可。这是因为如果n是一个合数,那么n可以分解为ab两个数,即n = a ✖️ b,那么这两个因数中必然有一个小于或等于sqrt(n),另一个大于或等于sqrt(n)。因此只需要找出小于或等于sqrt(n)的因数,既可以判断n是否为合数。这样大大减少了需要检测的除数数量,提高了效率。

具体解释

  1. 合数的性质​:如果一个大于1的整数n不是质数,那么它就是合数,并且一定存在其他的因子,除了1和它本身。
  2. 因数成对出现​:假设n是一个合数,我们可以将其分解成两个因子ab,使得n = a ✖️ b
  3. 平方根的意义​:
    • 如果a=b,那么pow(a,2) = n,意味着sqrt(n) = a,所以ab都等于sqrt(n)
    • 如果a≠b,那么必然有一个因子小于sqrt(n),另一个因子大于sqrt(n)。如果两个因数都大于sqrt(n),那它们的乘积一定大于n,反之则一定小于n
  4. 效率提升​:由于合数一定有一个因子小于或等于其平方根,那么当我们从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;
}