为什么每次迭代都由 i+6 完成,为什么这个素数测试函数的条件是 i*i<=n?

why the iteration is done by i+6 every time and why the condition is i*i<=n for this prime testing function?

本文关键字:为什么 条件 lt 函数 迭代 i+6 完成 测试      更新时间:2023-10-16

https://www.geeksforgeeks.org/primality-test-set-set-1-indroduction-and-school-school-method/

//基于优化的学校方法的C 程序检查//如果一个数字是prime

#include <bits/stdc++.h> 
using namespace std; 
bool isPrime(int n) 
{ 
    // Corner cases 
    if (n <= 1)  return false; 
    if (n <= 3)  return true; 
    // This is checked so that we can skip  
    // middle five numbers in below loop 
    if (n%2 == 0 || n%3 == 0) return false; 
    for (int i=5; i*i<=n; i=i+6) 
        if (n%i == 0 || n%(i+2) == 0) 
           return false; 
    return true; 
}

当您搜索素数时,您可以循环浏览2和您的数字之间的所有数字,以查看它们是否分为您的数字。

for (int i=2; i < n; i=i+1) 
    if (n%i == 0)
       return false; 

但这检查了您不需要的很多数字。
第一个观察结果(优化)是,只需进行一次划分一次检查,就已经检查了2个(偶数)的任何倍数(偶数)。

所以现在我们进行2支检查,然后跳过其他所有字符。

if (n%2 == 0 ) return false;
for (int i=3; i < n; i=i+2) 
    if (n%i == 0)
       return false; 

下一个观察结果(优化)是您可以为三个事情做几乎相同的事情。因此,第一个测试涵盖了2和3的所有组合。现在,在循环中您跳过每6个数字(2*3),并进行一些测试以涵盖所有不是2或3的数字。

if (n%2 == 0 || n%3 == 0) return false; 
for (int i=5; i<n; i=i+6) 
    if (n%i == 0 || n%(i+2) == 0) 
       return false; 

所以这只是一个优化,这意味着您不必尝试每个数字。

我们进行的下一个观察是,您不需要尝试大于N的平方根的数字(这些数字永远不会分为N)。因此,您可以将循环限制为i*i < n,因为i*isqrt(n)快。

if (n%2 == 0 || n%3 == 0) return false; 
for (int i=5; i*i<=n; i=i+6) 
    if (n%i == 0 || n%(i+2) == 0) 
       return false; 

尽管我个人会在循环周围每次进行sqrt(),而不是每次i*i。但这对于n的少量值可能会慢。

复合的任何数字至少将具有小于或等于其平方根的一个因素。为什么?因为如果它只有一个因素(自身或一个因素),则等于其平方根。如果有两个或多个,则最小的必须小于其平方根。因此,无需检查比平方根大的数字 - 如果不是素数,我们已经找到了一个因素。

代码早期检查2或3的代码。之后,我们只需要检查不是两个或三个倍数的因素。因此,在检查5和7之后,我们不需要检查6、8、9或10。因此,在每六个数字中,我们只需要检查两个不是两个或三个的倍数。