What is the fastest integer factorization algorithm?

后端 未结 8 1154
灰色年华
灰色年华 2020-11-28 01:49

I\'ve written a program that attempts to find Amicable Pairs. This requires finding the sums of the proper divisors of numbers.

Here is my current sumOfDiviso

相关标签:
8条回答
  • 2020-11-28 02:26

    I would suggest starting from the same algorithm used in Maple, the Quadratic Sieve.

    1. Choose your odd number n to factorize,
    2. Choose a natural number k,
    3. Search all p <= k so that k^2 is not congruent to (n mod p) to obtain a factor base B = p1, p2, ..., pt,
    4. Starting from r > floor(n) search at least t+1 values so that y^2 = r^2 - n all have just factors in B,
    5. For every y1, y2, ..., y(t+1) just calculated you generate a vector v(yi) = (e1, e2, ..., et) where ei is calculated by reducing over modulo 2 the exponent pi in yi,
    6. Use Gaussian Elimination to find some of the vectors that added together give a null vector
    7. Set x as the product of ri related to yi found in the previous step and set y as p1^a * p2^b * p3^c * .. * pt^z where exponents are the half of the exponents found in the factorization of yi
    8. Calculate d = mcd(x-y, n), if 1 < d < n then d is a non-trivial factor of n, otherwise start from step 2 choosing a bigger k.

    The problem about these algorithms is that they really imply a lot of theory in numerical calculus..

    0 讨论(0)
  • 2020-11-28 02:32

    This is an important open mathematical problem as of 2020

    Others have answered from a practical point of view, and there is high probability that for the problem sizes encountered in practice, that those algorithms are close to the optimal.

    However, I would also like to highlight, that the more general mathematical problem (in asymptotic computation complexity, i.e. as the number of bits tends to infinity) is completely unsolved.

    No one has ever been able to prove what is the minimal optimal time for of what is the fastest possible algorithm.

    This is shown on the Wikipedia page: https://en.wikipedia.org/wiki/Integer_factorization The algorithm also figures on Wiki's "List of unsolved problems in computer science" page: https://en.wikipedia.org/wiki/List_of_unsolved_problems_in_computer_science

    All that we know is that the best we currently have is the general number sieve. And until 2018, we didn't even have a non-heuristic proof for its complexity.

    As of 2020, we haven't even proved if the problem is NP-complete or not (although it is obviously NP since all you have to do to verify a solution is to multiply the numbers)! Although it is widely expected for it to be NP-complete. We can't be that bad at finding algorithms, can we?

    0 讨论(0)
  • 2020-11-28 02:38

    Depends how big your numbers are. If you're searching for amicable pairs you're doing a lot of factorisations, so the key may not be to factor as quickly as possible, but to share as much work as possible between different calls. To speed up trial division you could look at memoization, and/or precalculating primes up to the square root of the biggest number you care about. It's quicker to get the prime factorisation, then calculate the sum of all factors from that, than it is to loop all the way up to sqrt(n) for every number.

    If you're looking for really big amicable pairs, say bigger than 2^64, then on a small number of machines you can't do it by factorising every single number no matter how fast your factorisation is. The short-cuts which you're using to find candidates might help you factor them.

    0 讨论(0)
  • 2020-11-28 02:41

    Shor's Algorithm: http://en.wikipedia.org/wiki/Shor%27s_algorithm

    Of course you need a quantum computer though :D

    0 讨论(0)
  • 2020-11-28 02:41

    This is a paper of the Integer Factorization in Maple.

    "Starting from some very simple instructions—“make integer factorization faster in Maple” — we have implemented the Quadratic Sieve factoring algorithm in a combination of Maple and C..."

    http://www.cecm.sfu.ca/~pborwein/MITACS/papers/percival.pdf

    0 讨论(0)
  • 2020-11-28 02:43

    A more 2015 C++ version 227 lookup table implementation for 1GB memory:

    #include <iostream.h> // cerr, cout, and NULL
    #include <string.h>   // memcpy()
    #define uint unsigned __int32
    uint *factors;
    const uint MAX_F=134217728; // 2^27
    
    void buildFactors(){
       factors=new (nothrow) uint [(MAX_F+1)*2]; // 4 * 2 * 2^27 = 2^30 = 1GB
       if(factors==NULL)return; // not able to allocate enough free memory
       int i;
       for(i=0;i<(MAX_F+1)*2;i++)factors[i]=0;
    
       //Sieve of Eratosthenese
       factors[1*2]=1;
       factors[1*2+1]=1;
       for(i=2;i*i<=MAX_F;i++){
          for(;factors[i*2] && i*i<=MAX_F;i++);
          factors[i*2]=1;
          factors[i*2+1]=i;
          for(int j=2;i*j<=MAX_F;j++){
             factors[i*j*2]=i;
             factors[i*j*2+1]=j;
          }
       }
       for(;i<=MAX_F;i++){
          for(;i<=MAX_F && factors[i*2];i++);
          if(i>MAX_F)return;
          factors[i*2]=1;
          factors[i*2+1]=i;
       }
    }
    
    uint * factor(uint x, int &factorCount){
       if(x > MAX_F){factorCount=-1;return NULL;}
       uint tmp[70], at=x; int i=0;
       while(factors[at*2]>1){
          tmp[i++]=factors[at*2];
          cout<<"at:"<<at<<" tmp:"<<tmp[i-1]<<endl;
          at=factors[at*2+1];
       }
       if(i==0){
          cout<<"at:"<<x<<" tmp:1"<<endl;
          tmp[i++]=1;
          tmp[i++]=x;
       }else{
          cout<<"at:"<<at<<" tmp:1"<<endl;
          tmp[i++]=at;
       }
       factorCount=i;
       uint *ret=new (nothrow) uint [factorCount];
       if(ret!=NULL)
          memcpy(ret, tmp, sizeof(uint)*factorCount);
       return ret;
    }
    
    void main(){
       cout<<"Loading factors lookup table"<<endl;
       buildFactors(); if(factors==NULL){cerr<<"Need 1GB block of free memory"<<endl;return;}
       int size;
       uint x=30030;
       cout<<"\nFactoring: "<<x<<endl;
       uint *f=factor(x,size);
       if(size<0){cerr<<x<<" is too big to factor. Choose a number between 1 and "<<MAX_F<<endl;return;}
       else if(f==NULL){cerr<<"ran out of memory trying to factor "<<x<<endl;return;}
    
       cout<<"\nThe factors of: "<<x<<" {"<<f[0];
       for(int i=1;i<size;i++)
          cout<<", "<<f[i];
       cout<<"}"<<endl;
       delete [] f;
    
       x=30637;
       cout<<"\nFactoring: "<<x<<endl;
       f=factor(x,size);
       cout<<"\nThe factors of: "<<x<<" {"<<f[0];
       for(int i=1;i<size;i++)
          cout<<", "<<f[i];
       cout<<"}"<<endl;
       delete [] f;
       delete [] factors;
    }
    

    Update: or sacrificing some simplicity for a bit more range just past 228

    #include <iostream.h> // cerr, cout, and NULL
    #include <string.h>   // memcpy(), memset()
    
    //#define dbg(A) A
    #ifndef dbg
    #define dbg(A)
    #endif
    
    #define uint   unsigned __int32
    #define uint8  unsigned __int8
    #define uint16 unsigned __int16
    
    uint * factors;
    uint8  *factors08;
    uint16 *factors16;
    uint   *factors32;
    
    const uint LIMIT_16   = 514; // First 16-bit factor, 514 = 2*257
    const uint LIMIT_32   = 131074;// First 32-bit factor, 131074 = 2*65537
    const uint MAX_FACTOR = 268501119;
    //const uint64 LIMIT_64 = 8,589,934,594; // First 64-bit factor, 2^33+1
    
    const uint TABLE_SIZE = 268435456; // 2^28 => 4 * 2^28 = 2^30 = 1GB 32-bit table
    const uint o08=1, o16=257 ,o32=65665; //o64=4294934465
    // TableSize = 2^37 => 8 * 2^37 = 2^40 1TB 64-bit table
    //   => MaxFactor = 141,733,953,600
    
    /* Layout of factors[] array
    *  Indicies(32-bit)              i                 Value Size  AFactorOf(i)
    *  ----------------           ------               ----------  ----------------
    *  factors[0..128]            [1..513]             8-bit       factors08[i-o08]
    *  factors[129..65408]        [514..131073]        16-bit      factors16[i-o16]
    *  factors[65409..268435455]  [131074..268501119]  32-bit      factors32[i-o32]
    *
    * Note: stopping at i*i causes AFactorOf(i) to not always be LargestFactor(i)
    */
    void buildFactors(){
    dbg(cout<<"Allocating RAM"<<endl;)
       factors=new (nothrow) uint [TABLE_SIZE]; // 4 * 2^28 = 2^30 = 1GB
       if(factors==NULL)return; // not able to allocate enough free memory
       uint i,j;
       factors08 = (uint8 *)factors;
       factors16 = (uint16 *)factors;
       factors32 = factors;
    dbg(cout<<"Zeroing RAM"<<endl;)
       memset(factors,0,sizeof(uint)*TABLE_SIZE);
       //for(i=0;i<TABLE_SIZE;i++)factors[i]=0;
    
    //Sieve of Eratosthenese
         //8-bit values
    dbg(cout<<"Setting: 8-Bit Values"<<endl;)
       factors08[1-o08]=1;
       for(i=2;i*i<LIMIT_16;i++){
          for(;factors08[i-o08] && i*i<LIMIT_16;i++);
    dbg(cout<<"Filtering: "<<i<<endl;)
          factors08[i-o08]=1;
          for(j=2;i*j<LIMIT_16;j++)factors08[i*j-o08]=i;
          for(;i*j<LIMIT_32;j++)factors16[i*j-o16]=i;
          for(;i*j<=MAX_FACTOR;j++)factors32[i*j-o32]=i;
       }
       for(;i<LIMIT_16;i++){
          for(;i<LIMIT_16 && factors08[i-o08];i++);
    dbg(cout<<"Filtering: "<<i<<endl;)
          if(i<LIMIT_16){
             factors08[i-o08]=1;
             j=LIMIT_16/i+(LIMIT_16%i>0);
             for(;i*j<LIMIT_32;j++)factors16[i*j-o16]=i;
             for(;i*j<=MAX_FACTOR;j++)factors32[i*j-o32]=i;
          }
       }i--;
    
    dbg(cout<<"Setting: 16-Bit Values"<<endl;)
         //16-bit values
       for(;i*i<LIMIT_32;i++){
          for(;factors16[i-o16] && i*i<LIMIT_32;i++);
          factors16[i-o16]=1;
          for(j=2;i*j<LIMIT_32;j++)factors16[i*j-o16]=i;
          for(;i*j<=MAX_FACTOR;j++)factors32[i*j-o32]=i;
       }
       for(;i<LIMIT_32;i++){
          for(;i<LIMIT_32 && factors16[i-o16];i++);
          if(i<LIMIT_32){
             factors16[i-o16]=1;
             j=LIMIT_32/i+(LIMIT_32%i>0);
             for(;i*j<=MAX_FACTOR;j++)factors32[i*j-o32]=i;
          }
       }i--;
    
    dbg(cout<<"Setting: 32-Bit Values"<<endl;)
         //32-bit values
       for(;i*i<=MAX_FACTOR;i++){
          for(;factors32[i-o32] && i*i<=MAX_FACTOR;i++);
          factors32[i-o32]=1;
          for(j=2;i*j<=MAX_FACTOR;j++)factors32[i*j-o32]=i;
       }
       for(;i<=MAX_FACTOR;i++){
          for(;i<=MAX_FACTOR && factors32[i-o32];i++);
          if(i>MAX_FACTOR)return;
          factors32[i-o32]=1;
       }
    }
    
    uint * factor(uint x, int &factorCount){
       if(x > MAX_FACTOR){factorCount=-1;return NULL;}
       uint tmp[70], at=x; int i=0;
       while(at>=LIMIT_32 && factors32[at-o32]>1){
          tmp[i++]=factors32[at-o32];
    dbg(cout<<"at32:"<<at<<" tmp:"<<tmp[i-1]<<endl;)
          at/=tmp[i-1];
       }
       if(at<LIMIT_32){
          while(at>=LIMIT_16 && factors16[at-o16]>1){
             tmp[i++]=factors16[at-o16];
    dbg(cout<<"at16:"<<at<<" tmp:"<<tmp[i-1]<<endl;)
             at/=tmp[i-1];
          }
          if(at<LIMIT_16){
             while(factors08[at-o08]>1){
                tmp[i++]=factors08[at-o08];
    dbg(cout<<"at08:"<<at<<" tmp:"<<tmp[i-1]<<endl;)
                at/=tmp[i-1];
             }
          }
       }
       if(i==0){
    dbg(cout<<"at:"<<x<<" tmp:1"<<endl;)
          tmp[i++]=1;
          tmp[i++]=x;
       }else{
    dbg(cout<<"at:"<<at<<" tmp:1"<<endl;)
          tmp[i++]=at;
       }
       factorCount=i;
       uint *ret=new (nothrow) uint [factorCount];
       if(ret!=NULL)
          memcpy(ret, tmp, sizeof(uint)*factorCount);
       return ret;
    }
    uint AFactorOf(uint x){
       if(x > MAX_FACTOR)return -1;
       if(x < LIMIT_16) return factors08[x-o08];
       if(x < LIMIT_32) return factors16[x-o16];
                        return factors32[x-o32];
    }
    
    void main(){
       cout<<"Loading factors lookup table"<<endl;
       buildFactors(); if(factors==NULL){cerr<<"Need 1GB block of free memory"<<endl;return;}
       int size;
       uint x=13855127;//25255230;//30030;
       cout<<"\nFactoring: "<<x<<endl;
       uint *f=factor(x,size);
       if(size<0){cerr<<x<<" is too big to factor. Choose a number between 1 and "<<MAX_FACTOR<<endl;return;}
       else if(f==NULL){cerr<<"ran out of memory trying to factor "<<x<<endl;return;}
    
       cout<<"\nThe factors of: "<<x<<" {"<<f[0];
       for(int i=1;i<size;i++)
          cout<<", "<<f[i];
       cout<<"}"<<endl;
       delete [] f;
    
       x=30637;
       cout<<"\nFactoring: "<<x<<endl;
       f=factor(x,size);
       cout<<"\nThe factors of: "<<x<<" {"<<f[0];
       for(int i=1;i<size;i++)
          cout<<", "<<f[i];
       cout<<"}"<<endl;
       delete [] f;
       delete [] factors;
    }
    
    0 讨论(0)
提交回复
热议问题