Shanks kvadrat bildar faktorisering

Shanks fyrkantsformfaktorisering är en metod för heltalsfaktorisering utarbetad av Daniel Shanks som en förbättring av Fermats faktoriseringsmetod .

Framgången för Fermats metod beror på att hitta heltal och så att , där är det heltal som ska faktoriseras. En förbättring (märkt av Kraitchik ) är att leta efter heltal och så att . Att hitta ett lämpligt par garanterar inte en faktorisering av , men det innebär att är en faktor på och det finns en god chans att primtalsdivisorerna för N är fördelade mellan dessa två faktorer, så att beräkning av den största gemensamma divisorn för och ger en icke-trivial faktor på .

En praktisk algoritm för att hitta par som uppfyller utvecklades av Shanks, som kallade det Square Forms Factorization eller SQUFOF. Algoritmen kan uttryckas i termer av fortsatta bråk eller i termer av kvadratiska former. Även om det nu finns mycket effektivare faktoriseringsmetoder tillgängliga, har SQUFOF fördelen att den är tillräckligt liten för att kunna implementeras på en programmerbar kalkylator.

År 1858 använde den tjeckiske matematikern Václav Šimerka en metod liknande SQUFOF to factor .

Algoritm

Inmatning : , det heltal som ska faktoriseras, vilket varken får vara ett primtal eller en perfekt kvadrat , och en liten multiplikator .

Output : en icke-trivial faktor av .

Algoritmen:

Initiera

Upprepa

tills är en perfekt kvadrat vid vissa jämna .

Initiera

Upprepa

tills

Sedan om inte är lika med och inte lika med , då är en icke-trivial faktor av . Försök annars med ett annat värde på .

Shanks metod har tidskomplexitet .

Stephen S. McMath skrev en mer detaljerad diskussion om matematiken i Shanks metod, tillsammans med ett bevis på dess riktighet.

Exempel

Låt

Cykla framåt

Här är en perfekt kvadrat.

Omvänd cykel

Här .

, vilket är en faktor på .

Således är

Exempel på implementeringar

Nedan är ett exempel på C-funktion för att utföra SQUFOF-faktorisering på heltal utan tecken som inte är större än 64 bitar, utan översvämning av transientoperationerna. [ citat behövs ]

 


                   

    

              
       
      
         
        0         
          
              
          
            
              
            
                  
                
                
              
                  
              
                    
              
              
        
            
            
              
          
            
          0
         
                
              
                
              
                  
              
            
            
           
                 
    
     0
 #include  <inttypes.h>  #define nelems(x) (sizeof(x) / sizeof((x)[0]))  const  int  multiplikator  []  =  {  1  ,  3  ,  5  ,  7  ,  11  ,  3  *  5  ,  3  *  7  ,  3  *  11  ,  5  *  7  ,  5  *  11  ,  7  *  11  ,  3  *  5  *  7  ,  3  *  5  *  11  ,  3  *  7  *  11  ,  5  *  7  *  11  ,  3  *  5  *  7  *  11  };  uint64_t  SQUFOF  (  uint64_t  N  )  {  uint64_t  D  ,  Po  ,  P  ,  Pprev  ,  Q  ,  Qprev  ,  q  ,  b  ,  r  ,  s  ;  uint32_t  L  ,  B  ,  i  ;  s  =  (  uint64_t  )(  sqrtl  (  N  )  +  0,5  );  if  (  s  *  s  ==  N  )  returnera  s  ;  för  (  int  k  =  ;  k  <  nelems  (  multiplikator  )  &&  N  <=  UINT64_MAX  /  multiplikator  [  k  ];  k  ++  )  {  D  =  multiplikator  [  k  ]  *  N  ;  Po  =  Pprev  =  P  =  sqrtl  (  D  );  Qprev  =  1  ;  Q  =  D  -  Po  *  Po  ;  L  =  2  *  sqrtl  (  2  *  s  );  B  =  3  *  L  ;  för  (  i  =  2  ;  i  <  B  ;  i  ++  )  {  b  =  (  uint64_t  )((  Po  +  P  )  /  Q  );  P  =  b  *  Q  -  P  ;  q  =  Q  ;  Q  =  Qprev  +  b  *  (  Pprev  -  P  );  r  =  (  uint64_t  )(  sqrtl  (  Q  )  +  0,5  );  om  (  !  (  i  &  1  )  &&  r  *  r  ==  Q  )  break  ;  Qprev  =  q  ;  Pprev  =  P  ;  };  if  (  i  >=  B  )  fortsätt  ;  b  =  (  uint64_t  )((  Po  -  P  )  /  r  );  Pprev  =  P  =  b  *  r  +  P  ;  Qprev  =  r  ;  Q  =  (  D  -  Pprev  *  Pprev  )  /  Qprev  ;  i  =  ;  gör  {  b  =  (  uint64_t  )((  Po  +  P  )  /  Q  );  Pprev  =  P  ;  P  =  b  *  Q  -  P  ;  q  =  Q  ;  Q  =  Qprev  +  b  *  (  Pprev  -  P  );  Qprev  =  q  ;  i  ++  ;  }  while  (  P  !=  Föreg  );  r  =  gcd  (  N  ,  Qprev  );  if  (  r  !=  1  &&  r  !=  N  )  returnera  r  ;  }  returnera  ;  } 

externa länkar