简体   繁体   English

如何从 c++ 中的数组中获取最长的素数序列

[英]How to get the longest sequence of prime numbers from an array in c++

I'm trying to get the longest(largest) sequence of consecutive prime numbers from an array..我正在尝试从数组中获取最长(最大)的连续素数序列。

On first test with 10 elements in the array works, but when i tried with 15 elements like: 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 it spit out 4, which is incorrect.在第一次使用数组中的 10 个元素进行测试时,但是当我尝试使用 15 个元素时,例如:3、5、7、8、9、11、13、17、19、20、23、29、31、37、41吐出4,这是不正确的。

#include <iostream>
using namespace std;

int main()
{
    int bar[100];
    int x, j = 0;

    int maxseq = 0;
    int longestseqstart = 0;
    cout << "How big is the array? =";
    cin >> x;
    for (int i = 0; i < x; i++) {
        cout << "bar[" << i << "]=";
        cin >> bar[i];
    }
    for (int i = 1; i < x - 1; i = j) {
        int startseq = i;
        int seq = 0;

        j = i + 1;
        bool prim = true;
        int a = bar[i];
        for (int d = 2; d <= a / 2; d++) {
            if (a % d == 0) {
                prim = false;
            }
        }
        while (j < x && prim) {
            seq++;
            if (seq > maxseq) {
                maxseq = seq;
                longestseqstart = i;
            }
            int a = bar[j];
            for (int d = 2; d <= a / 2; d++) {
                if (a % d == 0) {
                    prim = false;
                }
            }
            j++;
        }
    }

    cout << "The longest sequence is: ";
    cout << maxseq;

    return 0;
}

You are checking twice for prime numbers and you are using a nested loop.您正在检查两次素数,并且您正在使用嵌套循环。 That's not necessary.那没有必要。 It's enough to read all numbers, check each number, increment the count if it's a prime number and store the maximum sequence length.读取所有数字,检查每个数字,如果它是质数则增加计数并存储最大序列长度就足够了。

#include <iostream>
#include <vector>
using namespace std;

bool isPrime(int a) {
    bool prim = true;
    for (int d = 2; d*d <= a; ++d) {
        if (a % d == 0) {
            prim = false;
        }
    }
    return prim;
}

int main()
{
    int x;

    int longestseqstart = 0;
    cout << "How big is the array? =";
    cin >> x;
    std::vector<int> bar(x);
    for (int i = 0; i < x; i++) {
        cout << "bar[" << i << "]=";
        cin >> bar[i];
    }

    unsigned int count = 0;
    unsigned int maxseq = 0;
    for (const auto &el : bar) {
        if (isPrime(el)) {
            ++count;
            if (count > maxseq) maxseq = count;
        } else count = 0;
    }
    cout << "The longest sequence is: ";
    cout << maxseq;

    return 0;
}

Of course you can avoid the usage of std::vector and functions with当然,您可以避免使用std::vector和函数

#include <iostream>
using namespace std;

int main()
{
    int x;

    int longestseqstart = 0;
    cout << "How big is the array? =";
    cin >> x;
    int bar[100];
    for (int i = 0; i < x; i++) {
        cout << "bar[" << i << "]=";
        cin >> bar[i];
    }

    unsigned int count = 0;
    unsigned int maxseq = 0;
    for (unsigned int i = 0; i < x; ++i) {
        int a = bar[i];
        bool prim = true;
        for (int d = 2; d*d <= a; ++d) {
            if (a % d == 0) {
                prim = false;
            }
        }
        if (prim) {
            ++count;
            if (count > maxseq) maxseq = count;
        } else count = 0;
    }
    cout << "The longest sequence is: ";
    cout << maxseq;

    return 0;
}

The algorithm looks basically OK.该算法看起来基本没问题。 The issue is mostly one of organization: the way the inner loop block is set up means that a run of primes will be short by 1 because the longest sequence is only updated at the beginning of the inner loop, missing the final prime.问题主要在于组织:内部循环块的设置方式意味着素数的运行将短 1,因为最长的序列仅在内部循环的开头更新,缺少最后的素数。

A couple of minimal failing examples are:几个最小的失败示例是:

How big is the array? =1
bar[0]=13
The longest sequence is: 0
How big is the array? =2
bar[0]=5
bar[1]=6
The longest sequence is: 0

Note that there's a repeated prime check in two places.请注意,在两个地方有重复的主要检查。 This should not be.这不应该。 If we move all of the prime logic into the loop and test for a new longest sequence only after finishing the entire run, we'll have a clear, accurate algorithm:如果我们将所有主要逻辑移入循环并仅在完成整个运行后测试新的最长序列,我们将拥有一个清晰、准确的算法:

#include <iostream>

int is_prime(int n) {
    for (int i = 2; i <= n / 2; i++) {
        if (n % i == 0) {
            return false;
        }
    }

    return true;
}

int main() {
    int nums[100];
    int n;
    std::cout << "How big is the array? =";
    std::cin >> n;

    for (int i = 0; i < n; i++) {
        std::cout << "nums[" << i << "]=";
        std::cin >> nums[i];
    }

    int longest = 0;

    for (int i = 0, start = 0; i < n; i++) {
        for (start = i; i < n && is_prime(nums[i]); i++);

        longest = std::max(longest, i - start);
    }

    std::cout << "The longest sequence is: " << longest;
    return 0;
}

In this rewrite I...在这次重写中,我...

  • avoided using namespace std; 避免using namespace std; . .
  • removed unnecessary/confusing variables.删除了不必要的/令人困惑的变量。
  • used clear variable names ( bar should only be used in example code when the name doesn't matter).使用明确的变量名称( bar应该只在名称无关紧要的示例代码中使用)。
  • moved is_prime to its own function.is_prime移至其自己的 function。

But there are outstanding issues with this code.但是这段代码存在一些突出的问题。 It should...它应该...

  • use a vector instead of an array.使用向量而不是数组。 As it stands, it's vulnerable to a buffer overflow attack should the user specify an array length > 100.就目前而言,如果用户指定的数组长度 > 100,它很容易受到缓冲区溢出攻击
  • use a faster method of finding primes .使用更快的方法找到素数 We only need to check up to the square root of the number and can skip a lot of numbers such as even numbers after 2. I suspect this is incidental to this exercise but it's worth mentioning.我们只需要检查数字的平方根,并且可以跳过很多数字,例如 2 之后的偶数。我怀疑这是本练习的附带问题,但值得一提。
  • move the longest_prime_sequence to a separate function (and possibly user input gathering as well).将最长的longest_prime_sequence移动到单独的 function (以及可能的用户输入收集)。

I would write the program the following way我会用以下方式编写程序

#include <iostream>
#include <iterator>
#include <algorithm>

bool is_prime( unsigned int n )
{
    bool prime = n % 2 == 0 ? n == 2 : n != 1;

    for ( unsigned int i = 3; prime && i <= n / i; i += 2 )
    {
        prime = n % i != 0;
    }

    return prime;
}


int main() 
{
    unsigned int a[] =  { 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 };
    const size_t N = sizeof( a ) / sizeof( *a );

    size_t maxseq = 0;

    for ( auto current = std::find_if( a, a + N, is_prime ); 
          current != a + N;
          current = std::find_if( current, a + N, is_prime ) )
    {
        auto first = current;
        current = std::find_if_not( current, a + N, is_prime );

        size_t n = std::distance( first, current );

        if ( maxseq < n ) maxseq = n;
    }

    std::cout << "The longest sequence is: " <<  maxseq << '\n';

    return 0;
}

The program output is程序 output 是

The longest sequence is: 5

I did not use generic functions std::begin( a ) and std::end( a ) because in your program the array can contain less actual elements than the array dimension.我没有使用通用函数std::begin( a )std::end( a )因为在您的程序中,数组可以包含比数组维度更少的实际元素。

If you do not know yet standard C++ algorithms then the program can be defined the following way如果您还不知道标准的 C++ 算法,那么可以通过以下方式定义程序

#include <iostream>

bool is_prime( unsigned int n )
{
    bool prime = n % 2 == 0 ? n == 2 : n != 1;

    for ( unsigned int i = 3; prime && i <= n / i; i += 2 )
    {
        prime = n % i != 0;
    }

    return prime;
}


int main() 
{
    unsigned int a[] =  { 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 };
    const size_t N = sizeof( a ) / sizeof( *a );

    size_t maxseq = 0;
    size_t n = 0;

    for ( size_t i = 0; i < N; i++ )
    {
        bool prime = a[i] % 2 == 0 ? a[i] == 2 : a[i] != 1;

        for ( unsigned int j = 3; prime && j <= a[i] / j; j += 2 )
        {
            prime = a[i] % j != 0;
        }

        if ( prime )
        {
            if ( maxseq < ++n ) maxseq = n;
        }
        else
        {
            n = 0;
        }
    }

    std::cout << "The longest sequence is: " <<  maxseq << '\n';

    return 0;
}

The program output is the same as above程序output同上

The longest sequence is: 5

As for your program then this loop至于你的程序,那么这个循环

for (int i = 1; i < x - 1; i = j) {

skips the first element of the array that is bar[0] .跳过数组的第一个元素bar[0]

And due to this statement并且由于这个声明

j = i + 1;

the calculated value of seq one less than it should be because you do not take into account that bar[i] is already prime. seq的计算值比它应该小一,因为你没有考虑到bar[i]已经是素数。

Set initially seq equal to 1.初始设置 seq 等于 1。

int seq = 1;

Moreover you incorrectly are determining prime numbers.此外,您错误地确定了素数。 For example according to your algorithm 1 is prime.例如,根据您的算法,1 是素数。

Convert the array to a Boolean array and find longest length.将数组转换为 Boolean 数组并找到最长的长度。 Try this snippet(not optimized):试试这个片段(未优化):

bool is_prime(int n) {
    for (int i = 2; i < n; i++) {
        if (n%i == 0) return false;
    }
    return true;
}

int main() {
    //Input
    unsigned int bar[15] = { 3, 5, 7, 8, 9, 11, 13, 17, 19, 20, 23, 29, 31, 37, 41 };
    // Convert input to boolean array
    bool boo[15];
    for (int i = 0; i < 15; i++) {
        boo[i] = is_prime(bar[i]);
    }
    //Check the longest boolean array
    int longest = 0;
    for (int i = 0; i < 15; i++) {
        int count = 0;

        while (boo[i + count] && (i+ count) <15) {
            count++;            
        }
        if (longest < count) longest = count;

    }
    //Output
    cout << longest;

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM