숫자의 가장 큰 소인수를 구하는 알고리즘


183

숫자의 가장 큰 소수를 계산하는 가장 좋은 방법은 무엇입니까?

가장 효율적인 것은 다음과 같습니다.

  1. 깨끗하게 나누는 가장 작은 소수를 찾으십시오.
  2. 분할 결과가 소수인지 확인
  3. 그렇지 않은 경우 다음 최저 찾기
  4. 2로 가십시오.

나는 작은 소수를 계산하기가 더 쉽다는 가정에 근거하고 있습니다. 이게 맞습니까? 다른 접근 방법은 무엇입니까?

편집 : 이제 2 가지 이상의 주요 요소가있는 경우 내 접근 방식이 쓸모가 없다는 것을 깨달았습니다. 결과가 두 개의 다른 소수의 곱일 때 2 단계가 실패하므로 재귀 알고리즘이 필요합니다.

다시 편집 : 그리고 마지막으로 발견 된 소수가 가장 높아야하므로 2 단계에서 비 프라임 결과를 추가로 테스트하면 소수가 작아지기 때문에 여전히 작동한다는 것을 알았습니다.


나의 접근 방식은 : (1) 가능한 큰 숫자를 2로 나눈다. (2) 큰 숫자가 고르게 나누어 져 있는지 확인하십시오. (3) 그렇다면 2로 나눈 숫자가 소수인지 확인하십시오. 그렇다면 반환하십시오. (4) 그렇지 않으면 1을 2에서 2로 나눈 값을 빼고 3 단계로 돌아갑니다.
Kevin Meredith

1.명확하게 나누는 (i = 2의 경우 int (sqr (num))) 2.해당 숫자로 나눈 숫자 (num = num / i)를 찾고 1에 아무것도 발견되지 않을 때까지 반복합니다 . 간격 3. num 이 가장 큰 요인
user3819867

1
우리는 작은 소수로

답변:


134

실제로 많은 수의 요인을 찾는 더 효율적인 방법이 몇 가지 있습니다 (소규모 분담이 합리적으로 잘 작동 함).

입력 숫자에 제곱근에 매우 가까운 두 가지 요인이있는 경우 매우 빠른 방법을 Fermat factorisation이라고 합니다. 그것은 N = (a + b) (a-b) = a ^ 2-b ^ 2라는 아이덴티티를 사용하며 이해하고 구현하기 쉽습니다. 불행히도 일반적으로 빠르지는 않습니다.

최대 100 자리의 숫자를 분해하는 가장 잘 알려진 방법은 2 차 체 입니다. 또한 알고리즘의 일부는 병렬 처리를 통해 쉽게 수행 할 수 있습니다.

내가 들었던 또 다른 알고리즘은 Pollard 's Rho algorithm 입니다. Quadratic Sieve만큼 효율적이지는 않지만 구현하기가 더 쉬운 것 같습니다.


숫자를 두 가지 요소로 나누는 방법을 결정한 후 숫자의 가장 큰 주요 요소를 찾는 가장 빠른 알고리즘은 다음과 같습니다.

처음에 숫자 자체를 저장하는 우선 순위 큐를 작성하십시오. 각 반복마다 큐에서 가장 높은 숫자를 제거하고 두 요소로 나눕니다 (물론 1이 해당 요소 중 하나가되지 않도록 함). 이 단계가 실패하면 숫자가 소수이며 답이됩니다! 그렇지 않으면 두 요인을 대기열에 추가하고 반복합니다.


3
Pollard rho와 elliptic curve 방법은 2 차 체보다 작은 소수 요소를 제거하는 데 훨씬 좋습니다. QS는 숫자에 관계없이 거의 동일한 런타임을 갖습니다. 어떤 접근 방식이 더 빠른지는 숫자에 따라 다릅니다. QS는 팩터링하기 어려운 숫자를 더 빨리 해독하는 반면, rho 및 ECM은 팩터링하기 쉬운 숫자를 더 빨리 해독합니다.
tmyklebu

2 차 변형 제안에 감사합니다. 나는 내 고객 중 하나를 위해 이것을 구현해야했습니다. 내가 처음 시작한 버전은 @mercutio가 그의 질문에서 제안한 내용을 따르는 것입니다. 이차 솔루션은 현재 math.tools/calculator/prime-factors 에서 고객의 툴을 강화하는 것 입니다.
dors

이 문제를 해결하는 효율적인 방법이 있다면 웹 암호화가 안전하지 않다는 의미가 아닙니까?
BKSpurgeon

141

내가 아는 가장 좋은 알고리즘은 다음과 같습니다 (파이썬)

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

위의 방법은 O(n)최악의 경우에 실행됩니다 (입력이 소수 인 경우).

편집 :
아래는 O(sqrt(n))의견에서 제안 된 버전입니다. 다음은 코드입니다.

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
투표하기 전에이 코드를 읽고 실행하십시오. 잘 작동합니다. 복사하여 붙여 넣기 만하면됩니다. 쓰여진 prime_factors (1000)은 [2,2,2,5,5,5]를 반환하는데, 이것은 2 ^ 3 * 5 ^ 3, 즉 소인수 분해로 해석되어야합니다.
삼부작

11
" O(sqrt(n))최악의 경우에 실행 "-아니오, O(n)최악의 경우에 실행됩니다 (예 : n소수 일 때 )
Sheldon L. Cooper

16
O (sqrt (n))으로 쉽게 만들려면 d * d> n 일 때 루프를 중지 하고이 시점에서 n> 1 인 경우 그 값을 소인수 목록에 추가해야합니다.
무두 페르난도

5
이것에 대한 이름이 있습니까?
Forethinker

11
2는 소수의 유일한 소수이므로 매번 1을 추가하는 대신 d = 2에 대해 별도로 반복 한 다음 1 씩 증가시킨 다음 d = 3부터 2 씩 증가시킬 수 있으므로 숫자가 감소합니다. of iterations ... :)
tailor_raj

18

내 대답은 Triptych를 기반으로 하지만 크게 향상됩니다. 2와 3을 넘어 모든 소수는 6n-1 또는 6n + 1 형식이라는 사실에 근거합니다.

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;
}

최근 에이 알고리즘의 작동 방식을 설명하는 블로그 기사를 작성했습니다 .

나는 원시성에 대한 테스트가 필요없는 (그리고 체 구성이없는) 방법이 그것을 사용하는 방법보다 더 빨리 실행될 것이라고 벤처 링 할 것입니다. 이 경우 아마도 가장 빠른 알고리즘 일 것입니다.


12
예를 들어 2,3,5를 넘어서이 아이디어를 실제로 더 가져올 수 있습니다. 모든 소수는 30n + k (n> = 0) 형식입니다. 여기서 k는 2에서 3으로 나눌 수없는 1에서 29 사이의 값만 취합니다. 또는 5, 즉 7,11,13,17,19,23,29. 지금까지 찾은 소수 몇 개마다 2 * 3 * 5 * 7 * ... * n + k까지이를 동적으로 조정할 수 있습니다. 여기서 k는 이러한 소수로 나눌 수 없어야합니다 (가능한 모든 k가 필요한 것은 아닙니다. 예를 들어 210n + k의 경우 121을 포함해야합니다. 그렇지 않으면 331을 놓치게됩니다 )
Tobias Kienzler

2
내 생각에while (multOfSix - 1 <= n)
Nader Ghanbari

8

자바 스크립트 코드 :

'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;
}

사용 예 :

let result = largestPrimeFactor(600851475143);

다음은 코드의 예입니다 .


7

@Triptych 답변과 비슷하지만 다릅니다. 이 예에서는 목록 또는 사전이 사용되지 않습니다. 코드는 루비로 작성되었습니다

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

마지막으로 읽기 쉽고 즉각적으로 (js로) 실행 가능한 것. 나는 무한 소수 목록을 사용하려고했지만 이미 1 백만에서 너무 느 렸습니다.
Ebuall

4

모든 숫자는 다음과 같이 소수의 곱으로 표현 될 수 있습니다.

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

간단히 2에서 시작하여 결과가 숫자의 배수가 될 때까지 계속 나누면됩니다.

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

이 방법을 사용하면 실제로 소수를 계산할 필요가 없습니다. 이전의 모든 숫자로 가능한 한 숫자를 이미 인수 화 한 사실에 따라 모두 소수가됩니다.

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.
}

예, 그러나 이것은 매우 비효율적입니다. 2를 모두 나누고 나면 실제로 4, 6으로 나누거나 시도하지 말아야합니다. 프라임 만 확인하거나 일부 알고리즘을 사용하는 것이 훨씬 효율적입니다.
wnoise

6
내가 잘못 생각하는 wnoise를 상쇄하기 위해 +1. 4로 나누려고하면 한 번만 발생하고 즉시 실패합니다. 나는 그것이 후보 목록에서 4를 제거하는 것보다 나쁘다고 생각하지 않으며, 모든 소수를 미리 찾는 것보다 확실히 빠릅니다.
삼부작

2
@Beowulf. 투표하기 전에이 코드를 실행하십시오. 주요 요소를 반환합니다. 알고리즘을 이해하지 못합니다.
Triptych 2012 년

3
코드는 정상적으로 작동하지만 들어오는 숫자가 소수이면 느립니다. 나는 또한 정사각형까지 올라가서 2 씩 증가 할 것입니다. 그러나 매우 큰 숫자에는 너무 느릴 수 있습니다.
blabla999

4
blabla999가 옳습니다. 예는 1234567898766700 = 2 * 2 * 5 * 5 * 12345678987667입니다. 에 도달하면 currFactor = 351364212345678987667이 소수이므로 답으로 반환해야합니다. 대신이 코드는 12345678987667 자체까지 열거를 계속합니다. 필요보다 3,513,642 배 느립니다.
Will 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
1,000,000,000,039로 코드를 사용해 보셨습니까? 눈을 깜박이는 상태에서도 작동해야합니다. 그렇습니까?
Will Ness

2
시도하지 않고 미리 알 수 있습니다. 10 ^ 12 = (2 * 5) ^ 12 = 2 ^ 12 * 5 ^ 12. 따라서 while루프는의 i값을 통과 합니다 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 개의 모든 반복. 그러나 (10 ^ 12 + 39)의 경우 (10 ^ 12 + 38) 반복이 i=2,3,4,5,6,...,10^12+39있습니다. 10 ^ 10 ops가 1 초가 걸리더라도 10 ^ 12는 100 초가 걸립니다. 그러나 10 ^ 6 반복 만 실제로 필요하며 10 ^ 10 ops에 1 초가 걸리면 10 ^ 6은 1 / 10,000 초가 걸립니다.
Will Ness

1
내가 알지 못했기 때문에 (10 ^ 12 + 39)는 내가하는 소수입니다. 나는 당신이 말하는 것을 정확히 얻습니다.
the_prole

1
좋아, 그래서 소수에 대한 큰 둔화가 없도록 코드를 변경할 수 있습니다 : 만약 n = a b 및 a <= b이면 a a <= b a = n, 즉 a a <= n . 만약 우리가 a + 1에 도달했다면, n은 반드시 소수입니다. (이를 통합하기 위해 답변을 편집하면 나에게 핑).
Will Ness

1
언제 발생 long n = 2*1000000000039L합니까? 최대한 빨리 작동합니까? 또한 return;명령문 을 사용하여 코드를 단순화 할 수 있습니까? (만약 내가 당신을 더럽 히지 않기를 원한다면 그렇게 말하십시오.)
Will Ness

4

가장 간단한 솔루션은 상호 재귀 쌍입니다 함수 .

첫 번째 함수는 모든 소수를 생성합니다.

  1. 1보다 큰 모든 자연수 목록으로 시작하십시오.
  2. 소수가 아닌 모든 숫자를 제거하십시오. 즉, 주요 요소가없는 숫자 (자체 이외). 아래를 참조하십시오.

두 번째 함수는 주어진 숫자의 소인수 n를 오름차순으로 반환합니다 .

  1. 모든 프라임 목록을 작성하십시오 (위 참조).
  2. 의 인수가 아닌 모든 숫자를 제거하십시오 n.

의 가장 큰 소인수 n는 두 번째 함수가 제공 한 마지막 수입니다.

이 알고리즘에는 게으른 목록 또는 필요에 따라 언어 (또는 데이터 구조)가 필요합니다 시맨틱이 합니다.

설명을 위해 Haskell에서 위의 (비효율적 인) 구현 중 하나가 있습니다.

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

이것을 더 빠르게하는 것은 어떤 숫자가 소수인지 및 / 또는 요인인지 감지하는 데 더 영리한 문제 n일 뿐이지 만 알고리즘은 동일하게 유지됩니다.


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와 3이 제거 된 경우 n을 6으로 나눌 수 없으므로 수퍼 플로어 인 일부 모듈로 테스트가 있습니다. i에 대한 소수만 허용 할 수 있으며 여기에 다른 답변이 나와 있습니다.

실제로 에라토스테네스의 체를 얽을 수 있습니다.

  • 먼저 sqrt (n)까지의 정수 목록을 작성하십시오.
  • for 루프에서 i의 모든 배수를 새로운 sqrt (n)까지 소수가 아닌 것으로 표시하고 대신 while 루프를 사용하십시오.
  • i를 목록의 다음 소수로 설정하십시오.

이 질문 도 참조하십시오 .


2

나는 이것이 빠른 해결책이 아니라는 것을 알고 있습니다. 느린 솔루션을 이해하기 쉽게 희망적으로 게시.

 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

숫자에서 모든 주요 요소를 제거하여 Python 반복 접근 방식

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

현재 숫자로 숫자를 계속 나누는 알고리즘을 사용하고 있습니다.

파이썬 3의 내 솔루션 :

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()))) 

입력 : 10 출력 :5

입력 : 600851475143 출력 :6857


0

C #에서 내 시도는 다음과 같습니다. 마지막 인쇄는 숫자의 가장 큰 주요 요소입니다. 확인하고 작동합니다.

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가 25의 가장 큰 주요 요소입니까?
Will Ness

0

C ++에서 재귀를 사용하여 숫자의 최대 소수를 계산합니다. 코드 작업은 다음과 같습니다.

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

가장 큰 주요 요소를 빠르게 계산하는 방법은 다음과 같습니다. 수정 x에는 기본이 아닌 요소가 포함되어 있지 않습니다. 이를 달성하기 위해 x요인이 발견되는 즉시 나눕니다 . 그런 다음 남은 것은 가장 큰 요소를 반환하는 것입니다. 이미 프라임 일 것입니다.

코드 (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

그러나 이것도 모든 짝수로 나누려고하지 않습니까?
야누스 Troelsen

0

다음 C ++ 알고리즘은 최고는 아니지만 10 억 미만의 숫자와 매우 빠른 속도로 작동합니다.

#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

웹에서 "James Wang"이이 솔루션을 찾았습니다.

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

체를 사용하는 주요 요인 :

#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

주어진 알고리즘의 2 단계가 모든 효율적인 접근 방식이 아닌 것 같습니다. 그것이 프라임이라는 합리적인 기대는 없습니다.

또한, 에라토스테네스의 체를 암시하는 이전의 대답은 완전히 잘못되었습니다. 방금 123456789를 고려하여 두 개의 프로그램을 작성했습니다. 하나는 Sieve를 기반으로하고 하나는 다음을 기반으로합니다.

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

이 버전은 체보다 90 배 빠릅니다.

문제는 최신 프로세서에서 작업 유형이 작업 수보다 훨씬 적다는 것입니다. 위의 알고리즘은 캐시에서 실행될 수 있지만 Sieve는 할 수 없습니다. 시브 (Sieve)는 모든 복합 수를 치는 많은 연산을 사용합니다.

또한 식별 된 요소를 구분하면 테스트해야 할 공간이 줄어 듭니다.


그것은 내가 말한 것이지만 투표에 실패했습니다 : (문제는 그 숫자가 정말로 큰 주요 요소 (예 : 자체)를 가지고 있다면이 방법은 그 숫자까지 반복해야한다는 것입니다. 많은 경우에
그러나이

당신을 통해 다시 읽는 것은 동일하지만 당신의 첫 번째 부분은 혼란 스럽습니다.
Loren Pechtel

이 번호로 143816789988504044536402352738195137863656439를 사용해보십시오. 이것이 얼마나 효율적인지 알려주세요.
MichaelICE

-1

소수를 먼저 저장하는 목록을 계산합니다 (예 : 2 3 5 7 11 13 ...

소수를 소인수 분해 할 때마다 Triptych에 의한 구현을 사용하되 자연 정수가 아닌이 소수리스트를 반복하십시오.


-1

자바로 :

에 대한 int값 :

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;
}

에 대한 long값 :

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

이것은 아마도 항상 빠르지는 않지만 큰 주요 제수를 찾는 것에 대해 더 낙관적입니다.

  1. N 당신의 번호입니다
  2. 그것이 프라임이라면 return(N)
  3. 까지 프라임 계산 Sqrt(N)
  4. 내림차순으로 소수 시작 (가장 큰 것부터)
    • 만약 N is divisible by Prime다음Return(Prime)

편집 : 3 단계에서 Eratosthenes의 체 또는 Atkins의 체 또는 원하는 것을 사용할 수 있지만 그 자체로는 체가 가장 큰 주요 요소를 찾지 못합니다. (그래서 내가 SQLMenace의 게시물을 공식 답변으로 선택하지 않는 이유는 ...)


1
소수를 결정하기 위해 시험 분해를 수행 할 필요가 없습니까 (2 단계)? 또한 가장 큰 소수 인 15를 찾는 것을 고려하십시오. sqrt (15)까지의 소수는 2와 3입니다. 그러나 가장 큰 주요 요소는 5입니다. 그렇지 않습니까? 마찬가지로 20.
Jonathan Leffler

-3

나는 가능한 모든 소수를 n보다 작게 저장하고 그것들을 반복하여 가장 큰 차이를 찾는 것이 좋을 것이라고 생각합니다. prime-numbers.org 에서 소수를 얻을 수 있습니다 .

물론 나는 당신의 숫자가 너무 크지 않다고 가정합니다 :)


-3

가장 빠르지는 않지만 작동합니다!

    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;
    }

이것은 질문에 대한 답변이 아닙니다. ;-) 문제는 우선 순위를 확인하지 않고 가장 큰 소수를 찾는 것에 관한 것입니다.
Hans-Peter Störr

(long i = 3; i <checkUpTo; i + = 2)와 같이 루프를 초기화하는 것이 훨씬 더 효율적입니다
cjk

-3

다음은 발전기로 제공되는 동일한 기능의 @Triptych이며, 약간 단순화되었습니다.

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

그러면 다음을 사용하여 최대 소수를 찾을 수 있습니다.

n= 373764623
max(primes(n))

다음을 사용하여 발견 된 요소 목록 :

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();
 }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.