Sieve of Eratosthenes - prime factor

2019-09-15 19:58发布

问题:

I just wrote the following to utilize the sieve to find the largest prime factor of some natural number greater than 2.

The program builds and runs and works for small test values, but simply crashes for values larger than, say, 1000000.

I wrote this myself--and believe it will probably be extremely inefficient--after finding out what the sieve is about.

Can you please suggest improvements?

Thank you.

//LARGEST PRIME FACTOR w/SIEVE OF ERATHOSTHENES
#include <iostream>
#include <math.h>

using namespace std;

unsigned long long int numberToCheck=0;

void sieve(unsigned long long int checkNumber)
{
    checkNumber=numberToCheck;
    unsigned long long int root=(int)(sqrt(checkNumber));
    unsigned long long int primeFlagger[checkNumber+1];

    for(unsigned long long int i=0;i<=checkNumber;i++)
    {
        primeFlagger[i]=1;
    }

    primeFlagger[0]=0;
    primeFlagger[1]=0;

    for(unsigned long long int j=2;j<=checkNumber;j++)
    {
        if(primeFlagger[j]==1)
        {
            for(unsigned long long int k=2;(k*j)<=checkNumber;k++)
            {
                primeFlagger[j*k]=0;
            }
        }
    }

    for(unsigned long long int l=checkNumber;l>=0;l--)
    {
        if(primeFlagger[l]==1)
        {
            if(checkNumber%l==0)
            {
                cout<<l<<" is the largest prime factor"<<endl;
                break;
            }
        }
    }
}

int main()
{
    cout<<"Largest prime factor less then or equal to? "<<endl;
    cin>>numberToCheck;
    cout<<endl;
    cout<<"Retrieving largest prime factor..."<<endl;

    sieve(numberToCheck);



    return 0;
}

回答1:

Your array unsigned long long int primeFlagger[checkNumber+1]; inside sieve func is too long. Use array in global scope, outside of any function or dynamic memory allocation.

Also, you dont need unsigned long long. Its a largest integer data type and you use only one bit of it. Changing type to bool will help you too.

There is other problems:

  • unsigned long long int root=(int)(sqrt(checkNumber)); - If number is really large, sqrt(checkNumber) can overflow int;
  • unsigned long long int primeFlagger[checkNumber+1]; - type of checkNumber is probably larger than std::size_t - the type for array index and larger than largest memory area that can be allocated. You just cant make array size of unsigned long long.
  • checkNumber=numberToCheck; - You dont need this. numberToCheck where already passed into function as parameter checkNumber. Inside sieve checkNummber will be equal to numberToCheck;
  • for(unsigned long long int j=2;j<=checkNumber;j++) - this loop should ends then j<=root. This would be enough to mark all non-primal numbers.

If you really need to work with such large numbers, use segmented sieve.