Bir sayının en büyük asal faktörünü bulmak için algoritma


183

Bir sayının en büyük asal çarpanını hesaplamak için en iyi yaklaşım nedir?

En verimli aşağıdaki olacağını düşünüyorum:

  1. Temiz bir şekilde bölünen en düşük asal sayıyı bulun
  2. Bölme sonucunun asal olup olmadığını kontrol edin
  3. Değilse, bir sonraki en düşük değeri bul
  4. Git 2.

Bu varsayımı, küçük asal faktörleri hesaplamanın daha kolay olduğuna dayandırıyorum. Bu doğru mu? Başka hangi yaklaşımlara bakmalıyım?

Düzenleme: Şimdi oyunda 2'den fazla asal faktör varsa benim yaklaşım boş olduğunu fark ettim, çünkü sonuç 2 diğer primerlerin bir ürünü olduğunda başarısız olur, bu nedenle tekrarlayan bir algoritma gereklidir.

Tekrar düzenleme: Ve şimdi bunun hala işe yaradığını fark ettim, çünkü son bulunan asal sayı en yüksek olmalıdır, bu nedenle 2. adımdan asal olmayan sonucun daha fazla test edilmesi daha küçük bir asal ile sonuçlanacaktır.


Benim yaklaşımım şuydu: (1) büyük, muhtemel sayıyı 2'ye bölmek; (2) büyük sayının eşit olarak bölünüp bölünmediğini kontrol edin; (3) öyleyse, 2 sayısına bölünmenin asal olup olmadığını kontrol edin. Eğer öyleyse, iade edin. (4) Başka, alt özet 1, 2 numaraya bölünür ve 3. adıma döner.
Kevin Meredith

1.açıkça bölen herhangi bir sayı bul (i = 2'den int'e (sqr (num))) 2.bu sayıya bölün (num = num / i) ve 1'de hiçbir şey bulunmadıkça tekrarlayın . 's aralık 3. num en büyük faktördür
user3819867

1
Küçük

Yanıtlar:


134

Aslında, büyük sayıların faktörlerini bulmanın birkaç daha etkili yolu vardır (küçük olanlar için deneme bölümü oldukça iyi çalışır).

Giriş sayısının kareköküne çok yakın iki faktörü varsa çok hızlı olan bir yönteme Fermat faktorizasyonu denir . N = (a + b) (a - b) = a ^ 2 - b ^ 2 kimliğinden yararlanır ve anlaşılması ve uygulanması kolaydır. Ne yazık ki genel olarak çok hızlı değil.

100 basamağa kadar olan sayıları çarpanlarına ayırmak için bilinen en iyi yöntem Karesel elektir . Bir bonus olarak, algoritmanın bir kısmı paralel işleme ile kolayca yapılır.

Duyduğum bir diğer algoritma Pollard'ın Rho algoritması . Genel olarak Kuadratik Elek kadar verimli değil, ancak uygulanması daha kolay görünüyor.


Bir sayının iki faktöre nasıl bölüneceğine karar verdikten sonra, bir sayının en büyük asal faktörünü bulmak için düşünebileceğim en hızlı algoritma:

Başlangıçta sayının kendisini saklayan bir öncelik kuyruğu oluşturun. Her yineleme, kuyruktan en yüksek sayıyı kaldırır ve iki faktöre ayırmaya çalışırsınız (elbette 1'in bu faktörlerden biri olmasına izin vermemek). Bu adım başarısız olursa, sayı asaldır ve cevabınızı alırsınız! Aksi takdirde iki faktörü kuyruğa ekleyip tekrar edersiniz.


3
Pollard rho ve eliptik eğri yöntemi, numaranızın küçük asal faktörlerinden kurtulmak için ikinci dereceden elekten çok daha iyidir. QS, sayı ne olursa olsun yaklaşık aynı çalışma süresine sahiptir. Hangi yaklaşımın daha hızlı olduğu, numaranızın ne olduğuna bağlıdır; QS, faktörler arası sayıları daha hızlı, rho ve ECM ise faktörler arası sayıları daha hızlı çözer.
tmyklebu

İkinci dereceden varyasyon önerisi için teşekkür ederiz. Bunu müşterilerimden biri için uygulamam gerekiyordu, ilk versiyonum, @mercutio'nun sorusunda önerdiği şey boyunca bir şeydi. İkinci dereceden çözüm, şu anda math.tools/calculator/prime-factors adresindeki müşterimin aracını güçlendiren şeydir .
dors

Bu sorunu çözmenin etkili bir yolu varsa, bu web şifrelemesinin güvenli olmadığı anlamına gelmez mi?
BKSpurgeon

141

İşte bildiğim en iyi algoritma (Python'da)

def prime_factors(n):
    """Returns all the prime factors of a positive integer"""
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        d = d + 1

    return factors


pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list

Yukarıdaki yöntem O(n)en kötü durumda çalışır (giriş asal sayı olduğunda).

EDIT:
Yorumda O(sqrt(n))önerildiği gibi sürüm aşağıdadır . İşte kod bir kez daha.

def prime_factors(n):
    """Returns all the prime factors of a positive integer"""
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        d = d + 1
        if d*d > n:
            if n > 1: factors.append(n)
            break
    return factors


pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list

11
Lütfen oylamadan önce bu kodu okuyun ve / veya çalıştırın. İyi çalışıyor. Sadece kopyalayıp yapıştırın. Yazıldığı gibi prime_factors (1000), 2 ^ 3 * 5 ^ 3, yani birincil çarpanlara ayırma olarak yorumlanması gereken [2,2,2,5,5,5] döndürecektir.
Triptik

11
" O(sqrt(n))En kötü durumda çalışır " - Hayır, O(n)en kötü durumda çalışır (örn. nen iyi zaman ).
Sheldon L. Cooper

16
Bunu yapmak kolay O (sqrt (n)), sadece d * d> n olduğunda döngüyü durdurursunuz ve bu noktada n> 1 ise, değeri asal faktörler listesine eklenmelidir.
Sumudu Fernando

5
Bunun için bir isim var mı?
Forethinker

11
2 tek çift asal sayı olduğundan, her seferinde 1 eklemek yerine, d = 2 için ayrı ayrı yineleyebilir ve sonra 1 değerini artırabilir ve sonra d = 3'ten itibaren 2'yi artırabilirsiniz, böylece sayıyı azaltacaktır. iterations ... :)
tailor_raj

18

Cevabım Triptych'e dayanıyor , ancak çok şey geliştiriyor. 2 ve 3'ün ötesinde, tüm asal sayıların 6n-1 veya 6n + 1 formunda olduğu gerçeğine dayanmaktadır.

var largestPrimeFactor;
if(n mod 2 == 0)
{
    largestPrimeFactor = 2;
    n = n / 2 while(n mod 2 == 0);
}
if(n mod 3 == 0)
{
    largestPrimeFactor = 3;
    n = n / 3 while(n mod 3 == 0);
}

multOfSix = 6;
while(multOfSix - 1 <= n)
{
    if(n mod (multOfSix - 1) == 0)
    {
        largestPrimeFactor = multOfSix - 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }

    if(n mod (multOfSix + 1) == 0)
    {
        largestPrimeFactor = multOfSix + 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }
    multOfSix += 6;
}

Geçenlerde bu algoritmanın nasıl çalıştığını açıklayan bir blog makalesi yazdım .

Öncelik için bir teste (ve elek yapımı yok) ihtiyaç duyulmayan bir yöntemin bunları kullananlardan daha hızlı çalışacağını düşünürdüm. Eğer durum buysa, bu muhtemelen buradaki en hızlı algoritmadır.


12
Aslında bu fikri daha da ileriye götürebilirsiniz, örneğin 2,3,5'ten fazla tüm asal değerler 30n + k (n> = 0) biçimindedir, burada k sadece 1 ile 29 arasında, 2,3 ile bölünemez olan değerleri alır veya 5, yani 7,11,13,17,19,23,29. Bunu, şimdiye kadar bulduğunuz her birkaç primerden sonra dinamik olarak adapte edebilirsiniz, buradaki k, bu primerlerden herhangi biri tarafından bölünemez olmalıdır (tüm olası k ihtiyaçlarının bulunmadığını unutmayın) aksi takdirde özleyeceğini, sen 121 eklemek zorunda k + 210N için örneğin asal 331 )
Tobias Kienzler

2
Sanırım olması gerektiğiwhile (multOfSix - 1 <= n)
Nader Ghanbari

8

JavaScript kodu:

'option strict';

function largestPrimeFactor(val, divisor = 2) { 
    let square = (val) => Math.pow(val, 2);

    while ((val % divisor) != 0 && square(divisor) <= val) {
        divisor++;
    }

    return square(divisor) <= val
        ? largestPrimeFactor(val / divisor, divisor)
        : val;
}

Kullanım Örneği:

let result = largestPrimeFactor(600851475143);

Kodun bir örneği :


7

@Triptych yanıtına benzer, ancak aynı zamanda farklı. Bu örnekte liste veya sözlük kullanılmamaktadır. Kod Ruby'de yazılmıştır

def largest_prime_factor(number)
  i = 2
  while number > 1
    if number % i == 0
      number /= i;
    else
      i += 1
    end
  end
  return i
end

largest_prime_factor(600851475143)
# => 6857

Sonunda aynı anda okunabilir ve anında (js olarak) çalıştırılabilir bir şey. Sonsuz asal listeyi kullanmaya çalışıyordum ve zaten 1 milyonda çok yavaştı.
Ebuall

4

Tüm sayılar, primerlerin ürünü olarak ifade edilebilir, örneğin:

102 = 2 x 3 x 17
712 = 2 x 2 x 2 x 89

Bunları 2'den başlayıp sonuç numaranızın katları oluncaya kadar bölmeye devam ederek bulabilirsiniz:

712 / 2 = 356 .. 356 / 2 = 178 .. 178 / 2 = 89 .. 89 / 89 = 1

bu yöntemi kullanarak herhangi bir asal değeri hesaplamanıza gerek yoktur: sayıyı daha önce tüm sayılarla mümkün olduğunca çarpanlarına ayırdığınız gerçeğine dayanarak hepsi asal olacaktır.

number = 712;
currNum = number;    // the value we'll actually be working with
for (currFactor in 2 .. number) {
    while (currNum % currFactor == 0) {
        // keep on dividing by this number until we can divide no more!
        currNum = currNum / currFactor     // reduce the currNum
    }
    if (currNum == 1) return currFactor;    // once it hits 1, we're done.
}

Evet, ama bu çok verimsiz. Tüm 2'leri böldüğünüzde, gerçekten 4 veya 6'ya bölmeyi denememelisiniz veya ...; Sadece primerleri kontrol etmek veya bazı toher algoritmaları kullanmak sınırında çok daha etkilidir.
wnoise

6
+ 1'i yanlış düşünmek için 4'e bölmeye çalışmak sadece bir kez olur ve hemen başarısız olur. Bunun bazı adaylar listesinden 4 çıkarılmasından daha kötü olduğunu düşünmüyorum ve önceden tüm asalları bulmaktan kesinlikle daha hızlı.
Triptik

2
@Beowulf. Oy vermeden önce bu kodu çalıştırmayı deneyin. Asal faktörleri döndürür; algoritmayı anlamıyorsunuz.
Triptik

3
kod iyi çalışıyor, ancak gelen numara asalsa yavaştır. Ayrıca sadece kareye kadar yükselir ve 2 artarım. Çok büyük sayılar için çok yavaş olabilir.
blabla999

4
blabla999 kesinlikle doğru. Örnek 1234567898766700 = 2 * 2 * 5 * 5 * 12345678987667'dir. Biz ulaştığınızda currFactor = 3513642, biz 12345678987667 asal olduğunu biliyoruz ve cevap olarak dönmelidir. Bunun yerine, bu kod numaralandırmaya 12345678987667 kadar devam edecektir. Bu 3.513.642x gerekenden daha yavaş.
Ness

4
    //this method skips unnecessary trial divisions and makes 
    //trial division more feasible for finding large primes

    public static void main(String[] args) 
    {
        long n= 1000000000039L; //this is a large prime number 
        long i = 2L;
        int test = 0;

        while (n > 1)
        {
            while (n % i == 0)
            {
                n /= i;     
            }

            i++;

            if(i*i > n && n > 1) 
            {
                System.out.println(n); //prints n if it's prime
                test = 1;
                break;
            }
        }

        if (test == 0)  
            System.out.println(i-1); //prints n if it's the largest prime factor
    }

1
Kodunuzu 1.000.000.000.039 ile denediniz mi? göz açıp kapayıncaya kadar koşmalıdır. Yapar?
Ness Ness

2
Bunu denemeden önceden biliyordun. 10 ^ 12 = (2 * 5) ^ 12 = 2 ^ 12 * 5 ^ 12. Böylece whiledöngünüzün ideğerleri geçer 2,2,2,2,2,2,2,2,2,2,2,2, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5. 60 iterasyonun hepsi. Ancak (10 ^ 12 + 39) için (10 ^ 12 + 38) yineleme olacaktır i=2,3,4,5,6,...,10^12+39. 10 ^ 10 ops bir saniye sürse bile, 10 ^ 12 100 saniye sürecektir. Ancak sadece 10 ^ 6 yineleme gerçekten gereklidir ve 10 ^ 10 ops bir saniye alırsa, 10 ^ 6 saniyenin 1 / 10.000'ini alır.
Ness Ness

1
Çünkü (10 ^ 12 + 39) şu anda yaptığım asal sayı olduğunu fark etmedim. Söylediklerini tam olarak anlıyorum.
the_prole

1
Tamam, böylece kodunuzu primerler için büyük bir yavaşlama olmayacak şekilde değiştirebilirsiniz: n = a b ve <= b ise, o zaman a a = = b a = n, yani a <= n . Ve eğer + 1'e ulaşırsak, n kesinlikle bir başbakan olur. (bunu eklemek için cevabınızı düzenlerseniz bana ping atın).
Ness Ness

1
ne zaman ne olur long n = 2*1000000000039L? Gerektiği kadar hızlı çalışıyor mu? (ayrıca, bir return;ifade kullanarak kodunuzu basitleştirebilir misiniz ?). (seni sürüklemeyi bırakmamı istiyorsan, sadece söyle;))
Ness

4

En basit çözüm, bir çift karşılıklı özyinelemeli işlevdir.

İlk işlev tüm asal sayıları oluşturur:

  1. 1'den büyük tüm doğal sayıların bir listesiyle başlayın.
  2. Asal olmayan tüm sayıları kaldırın. Yani, asal faktörleri olmayan sayılar (kendileri dışında). Aşağıya bakınız.

İkinci işlev, belirli bir sayının asal faktörlerini nartan sırada döndürür .

  1. Tüm asal sayıların bir listesini alın (yukarıya bakın).
  2. Faktörü olmayan tüm sayıları kaldırın n.

En büyük asal faktör n, ikinci fonksiyon tarafından verilen son sayıdır.

Bu algoritma, tembel çağrı semantiğine sahip tembel bir liste veya bir dil (veya veri yapısı) gerektirir .

Açıklamak için, yukarıdakilerin Haskell'de bir (verimsiz) uygulaması:

import Control.Monad

-- All the primes
primes = 2 : filter (ap (<=) (head . primeFactors)) [3,5..]

-- Gives the prime factors of its argument
primeFactors = factor primes
  where factor [] n = []
        factor xs@(p:ps) n =
          if p*p > n then [n]
          else let (d,r) = divMod n p in
            if r == 0 then p : factor xs d
            else factor ps n

-- Gives the largest prime factor of its argument
largestFactor = last . primeFactors

Bunu daha hızlı hale getirmek, sadece hangi sayıların asal ve / veya faktörlerin olduğunu tespit etme konusunda daha akıllı olma meselesidir n, ancak algoritma aynı kalır.


2
n = abs(number);
result = 1;
if (n mod 2 == 0) {
  result = 2;
  while (n mod 2 = 0) n /= 2;
}
for(i=3; i<sqrt(n); i+=2) {
  if (n mod i == 0) {
    result = i;
    while (n mod i = 0)  n /= i;
  }
}
return max(n,result)

2 ve 3 tüm faktörler çıkarılmışsa n asla 6'ya bölünemeyeceğinden, gereksiz olan bazı modulo testleri vardır. Burada i için sadece bazı diğer cevaplarda gösterilen i'ye izin verebilirsiniz.

Aslında burada Eratosthenes'in eleklerini iç içe geçirebilirsiniz:

  • Önce sqrt (n) 'ye kadar tamsayıların listesini oluşturun.
  • For döngüsünde, i'nin tüm katlarını yeni sqrt'a (n) kadar asal olarak işaretleyin ve bunun yerine while döngüsünü kullanın.
  • i'yi listedeki bir sonraki asal sayıya ayarlar.

Ayrıca bu soruya bakın .


2

Bunun hızlı bir çözüm olmadığının farkındayım. Yavaş bir çözüm anlamak umuyoruz daha kolay olarak.

 public static long largestPrimeFactor(long n) {

        // largest composite factor must be smaller than sqrt
        long sqrt = (long)Math.ceil(Math.sqrt((double)n));

        long largest = -1;

        for(long i = 2; i <= sqrt; i++) {
            if(n % i == 0) {
                long test = largestPrimeFactor(n/i);
                if(test > largest) {
                    largest = test;
                }
            }
        }

        if(largest != -1) {
            return largest;
        }

        // number is prime
        return n;
    } 

1

Sayıdan tüm asal faktörleri kaldırarak Python İteratif yaklaşım

def primef(n):
    if n <= 3:
        return n
    if n % 2 == 0:
        return primef(n/2)
    elif n % 3 ==0:
        return primef(n/3)
    else:
        for i in range(5, int((n)**0.5) + 1, 6):
            #print i
            if n % i == 0:
                return primef(n/i)
            if n % (i + 2) == 0:
                return primef(n/(i+2))
    return n

1

Sayıyı mevcut Prime Factor ile bölmeye devam eden algoritma kullanıyorum.

Python 3'teki Çözümüm:

def PrimeFactor(n):
    m = n
    while n%2==0:
        n = n//2
    if n == 1:         # check if only 2 is largest Prime Factor 
        return 2
    i = 3
    sqrt = int(m**(0.5))  # loop till square root of number
    last = 0              # to store last prime Factor i.e. Largest Prime Factor
    while i <= sqrt :
        while n%i == 0:
            n = n//i       # reduce the number by dividing it by it's Prime Factor
            last = i
        i+=2
    if n> last:            # the remaining number(n) is also Factor of number 
        return n
    else:
        return last
print(PrimeFactor(int(input()))) 

Giriş: 10 Çıkış:5

Giriş: 600851475143 Çıkış:6857


0

İşte c # denemem. Son çıktı, sayının en büyük asal faktörüdür. Kontrol ettim ve işe yarıyor.

namespace Problem_Prime
{
  class Program
  {
    static void Main(string[] args)
    {
      /*
       The prime factors of 13195 are 5, 7, 13 and 29.

      What is the largest prime factor of the number 600851475143 ?
       */
      long x = 600851475143;
      long y = 2;
      while (y < x)
      {
        if (x % y == 0)
        {
          // y is a factor of x, but is it prime
          if (IsPrime(y))
          {
            Console.WriteLine(y);
          }
          x /= y;
        }

        y++;

      }
      Console.WriteLine(y);
      Console.ReadLine();
    }
    static bool IsPrime(long number)
    {
      //check for evenness
      if (number % 2 == 0)
      {
        if (number == 2)
        {
          return true;
        }
        return false;
      }
      //don't need to check past the square root
      long max = (long)Math.Sqrt(number);
      for (int i = 3; i <= max; i += 2)
      {
        if ((number % i) == 0)
        {
          return false;
        }
      }
      return true;
    }

  }
}

0
#python implementation
import math
n = 600851475143
i = 2
factors=set([])
while i<math.sqrt(n):
   while n%i==0:
       n=n/i
       factors.add(i)
   i+=1
factors.add(n)
largest=max(factors)
print factors
print largest

1
25 en büyük asal faktör nedir?
Ness Ness

0

C ++ 'da özyineleme kullanarak bir sayının en büyük asal çarpanını hesaplar. Kodun çalışması aşağıda açıklanmaktadır:

int getLargestPrime(int number) {
    int factor = number; // assumes that the largest prime factor is the number itself
    for (int i = 2; (i*i) <= number; i++) { // iterates to the square root of the number till it finds the first(smallest) factor
        if (number % i == 0) { // checks if the current number(i) is a factor
            factor = max(i, number / i); // stores the larger number among the factors
            break; // breaks the loop on when a factor is found
        }
    }
    if (factor == number) // base case of recursion
        return number;
    return getLargestPrime(factor); // recursively calls itself
}

0

İşte en büyük asal faktörü hızlı bir şekilde hesaplamak için yaklaşımım. Değiştirilmiş xolanın asal olmayan faktörler içermemesine dayanır . Bunu başarmak için, xbir faktör bulunur bulunmaz bölünürüz. Sonra, geriye kalan tek şey en büyük faktörü döndürmektir. Zaten asal olurdu.

Kod (Haskell):

f max' x i | i > x = max'
           | x `rem` i == 0 = f i (x `div` i) i  -- Divide x by its factor
           | otherwise = f max' x (i + 1)  -- Check for the next possible factor

g x = f 2 x 2

ancak bu tüm çift sayılarla da bölünmeye çalışmaz mı?
Janus Troelsen

0

Aşağıdaki C ++ algoritması en iyisi değil, ancak bir milyarın altındaki sayılar ve oldukça hızlı

#include <iostream>
using namespace std;

// ------ is_prime ------
// Determines if the integer accepted is prime or not
bool is_prime(int n){
    int i,count=0;
    if(n==1 || n==2)
      return true;
    if(n%2==0)
      return false;
    for(i=1;i<=n;i++){
    if(n%i==0)
        count++;
    }
    if(count==2)
      return true;
    else
      return false;
 }
 // ------ nextPrime -------
 // Finds and returns the next prime number
 int nextPrime(int prime){
     bool a = false;
     while (a == false){
         prime++;
         if (is_prime(prime))
            a = true;
     }
  return prime;
 }
 // ----- M A I N ------
 int main(){

      int value = 13195;
      int prime = 2;
      bool done = false;

      while (done == false){
          if (value%prime == 0){
             value = value/prime;
             if (is_prime(value)){
                 done = true;
             }
          } else {
             prime = nextPrime(prime);
          }
      }
        cout << "Largest prime factor: " << value << endl;
 }

0

Bu çözümü web'de "James Wang" tarafından buldum

public static int getLargestPrime( int number) {

    if (number <= 1) return -1;

    for (int i = number - 1; i > 1; i--) {
        if (number % i == 0) {
            number = i;
        }
    }
    return number;
}

0

Elek kullanarak ana faktör:

#include <bits/stdc++.h>
using namespace std;
#define N 10001  
typedef long long ll;
bool visit[N];
vector<int> prime;

void sieve()
{
            memset( visit , 0 , sizeof(visit));
            for( int i=2;i<N;i++ )
            {
                if( visit[i] == 0)
                {
                    prime.push_back(i);
                    for( int j=i*2; j<N; j=j+i )
                    {
                        visit[j] = 1;
                    }
                }
            }   
}
void sol(long long n, vector<int>&prime)
{
            ll ans = n;
            for(int i=0; i<prime.size() || prime[i]>n; i++)
            {
                while(n%prime[i]==0)
                {
                    n=n/prime[i];
                    ans = prime[i];
                }
            }
            ans = max(ans, n);
            cout<<ans<<endl;
}
int main() 
{
           ll tc, n;
           sieve();

           cin>>n;
           sol(n, prime);

           return 0;
}

-1

Bana öyle geliyor ki, verilen algoritmanın 2. adımı o kadar etkili bir yaklaşım olmayacak. Asal olduğuna dair makul bir beklentiniz yok.

Ayrıca, Eratosthenes Elekini gösteren önceki cevap tamamen yanlıştır. 123456789 faktörüne yönelik iki program yazdım. Biri Elek, diğeri aşağıdakilere dayanıyordu:

1)  Test = 2 
2)  Current = Number to test 
3)  If Current Mod Test = 0 then  
3a)     Current = Current Div Test 
3b)     Largest = Test
3c)     Goto 3. 
4)  Inc(Test) 
5)  If Current < Test goto 4
6)  Return Largest

Bu versiyon Elek'ten 90 kat daha hızlıydı.

Mesele şu ki, modern işlemcilerde işlem türü, işlem sayısından çok daha az önemlidir, yukarıdaki algoritmanın önbellekte çalışabileceğinden bahsetmemek gerekirse, Elek yapamaz. Elek, tüm kompozit sayılara çarpan birçok işlem kullanır.

Ayrıca, tanımlandıkları gibi bölme faktörlerimin test edilmesi gereken alanı azalttığını unutmayın.


Ben söyledim, ama aşağı oy var :( Sanırım sorun gerçekten büyük bir asal çarpanı (kendisi gibi) varsa, o zaman bu yöntem bu sayı kadar sonuna kadar döngü gerekir. Ancak, bu yöntem oldukça etkilidir.
nickf

Sizinkini tekrar okumak aynı ama ilk bölümünüz kafa karıştırıcı.
Loren Pechtel

Bu numarayı deneyin 143816789988504044536402352738195137863656439, bunun ne kadar verimli olduğunu bana bildirin ...
MichaelICE

-1

Önce asal sayıları saklayan bir liste hesaplayın, örneğin 2 3 5 7 11 13 ...

Bir sayıyı çarpanlarına ayırdığınız her seferinde Triptych ile uygulamayı kullanın, ancak doğal tamsayılardan ziyade bu asal sayılar listesini yineleyin.


-1

Java ile:

İçin intdeğerler:

public static int[] primeFactors(int value) {
    int[] a = new int[31];
    int i = 0, j;
    int num = value;
    while (num % 2 == 0) {
        a[i++] = 2;
        num /= 2;
    }
    j = 3;
    while (j <= Math.sqrt(num) + 1) {
        if (num % j == 0) {
            a[i++] = j;
            num /= j;
        } else {
            j += 2;
        }
    }
    if (num > 1) {
        a[i++] = num;
    }
    int[] b = Arrays.copyOf(a, i);
    return b;
}

İçin longdeğerler:

static long[] getFactors(long value) {
    long[] a = new long[63];
    int i = 0;
    long num = value;
    while (num % 2 == 0) {
        a[i++] = 2;
        num /= 2;
    }
    long j = 3;
    while (j <= Math.sqrt(num) + 1) {
        if (num % j == 0) {
            a[i++] = j;
            num /= j;
        } else {
            j += 2;
        }
    }
    if (num > 1) {
        a[i++] = num;
    }
    long[] b = Arrays.copyOf(a, i);
    return b;
}

-2

Bu muhtemelen her zaman daha hızlı değil, büyük bir ana bölen bulmanız konusunda daha iyimser:

  1. N numaran mı
  2. Eğer asal ise return(N)
  3. Asal sayıları hesaplayın Sqrt(N)
  4. Asal sayıları azalan sırada (ilk önce en büyüğü)
    • Eğer N is divisible by PrimeöyleyseReturn(Prime)

Düzenleme: Adım 3'te Eratosthenes Elek veya Atkins Elek veya ne istersen kullanabilirsiniz, ama tek başına elek size en büyük ana faktörü bulamaz. (Bu yüzden SQLMenace'in gönderisini resmi bir cevap olarak seçmem ...)


1
Asal sayı olup olmadığını belirlemek için deneme faktörünü yapmanız gerekmez mi (2. adım)? Ayrıca, 15'in en büyük asal faktörünü bulmayı düşünün. ama en büyük asal faktör 5'tir, değil mi? Benzer şekilde 20.
Jonathan Leffler

-3

Bence n'den küçük tüm olası primes bir yerde saklamak ve sadece en büyük bölüneni bulmak için onları tekrarlamak iyi olurdu. Asalları prime-numbers.org adresinden alabilirsiniz .

Tabii ki sayınızın çok büyük olmadığını varsayıyorum :)


-3

En hızlı değil ama işe yarıyor!

    static bool IsPrime(long num)
    {
        long checkUpTo = (long)Math.Ceiling(Math.Sqrt(num));
        for (long i = 2; i <= checkUpTo; i++)
        {
            if (num % i == 0)
                return false;
        }
        return true;
    }

Bu sorunun cevabı değil. ;-) Asıl soru, öncelikliliği kontrol etmek değil, en büyük asal faktörü bulmaktı.
Hans-Peter Störr

Döngünüzü (uzun i = 3; i <checkUpTo; i + = 2) olarak başlatmak çok daha etkilidir
cjk

-3

İşte aynı zamanda hafifçe basitleştirilmiş bir jeneratör olarak sağlanan @ Triptych işlevi.

def primes(n):
    d = 2
    while (n > 1):
        while (n%d==0):
            yield d
            n /= d
        d += 1

maksimum asal daha sonra şu şekilde bulunabilir:

n= 373764623
max(primes(n))

ve aşağıdakileri kullanarak bulunan faktörlerin bir listesi:

list(primes(n))

-6
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include <time.h>

factor(long int n)
{
long int i,j;
while(n>=4)
 {
if(n%2==0) {  n=n/2;   i=2;   }

 else
 { i=3;
j=0;
  while(j==0)
  {
   if(n%i==0)
   {j=1;
   n=n/i;
   }
   i=i+2;
  }
 i-=2;
 }
 }
return i;
 }

 void main()
 { 
  clock_t start = clock();
  long int n,sp;
  clrscr();
  printf("enter value of n");
  scanf("%ld",&n);
  sp=factor(n);
  printf("largest prime factor is %ld",sp);

  printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);
  getch();
 }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.