Алгоритм знаходження найбільшого основного множника числа


183

Який найкращий підхід до обчислення найбільшого простого множника числа?

Я думаю, що найбільш ефективним буде таке:

  1. Знайдіть найнижнє просте число, яке чітко ділиться
  2. Перевірте, чи є результат ділення простим
  3. Якщо ні, знайдіть наступний найнижчий
  4. Перейти до 2.

Я ґрунтую це припущення на тому, що простіше обчислити малі основні фактори. Це правильно? Які ще підходи слід переглянути?

Редагувати: Зараз я зрозумів, що мій підхід є марним, якщо в грі більше двох основних факторів, оскільки крок 2 не вдається, коли результат є продуктом двох інших прайменів, тому потрібен рекурсивний алгоритм.

Змінити ще раз: І тепер я зрозумів, що це все-таки працює, тому що останній знайдений простий номер повинен бути найвищим, тому будь-яке подальше тестування непросте результату з кроку 2 призведе до меншого простору.


Мій підхід: 1) розділити велике, можливе число на 2; (2) перевірити, чи велика кількість рівномірно ділиться на ній; (3) якщо так, перевірте, чи розділене на 2 число є простим. Якщо є, поверніть його. (4) Інакше, підрив 1 із розділеного на 2 числа, повернення до кроку 3.
Кевін Мередіт,

1.знайти будь-яке число , яке ділить ясно (для я = 2 Int (SQR (NUM))) 2.розділити на це число (число = Num / я) і RECUR поки нічого не знайдено в 1. «s інтервал 3. NUM представляє собою найбільший фактор
user3819867

1
Ми можемо розділити невеликими праймерами, а той, який нарешті залишився, - це найбільший

Відповіді:


134

Насправді існує кілька більш ефективних способів пошуку факторів великої кількості (для менших пробний поділ працює досить добре).

Один метод, який дуже швидкий, якщо число вхідних даних має два коефіцієнти, близькі до квадратного кореня, відомий як факторизація Ферма . Він використовує тотожність N = (a + b) (a - b) = a ^ 2 - b ^ 2 і легко зрозуміти та реалізувати. На жаль, загалом це не дуже швидко.

Найвідомішим методом розбиття чисел до 100 цифр є квадратичне сито . Як бонус, частина алгоритму легко виконується при паралельній обробці.

Ще один алгоритм, про який я чув, це алгоритм Rho Полларда . Це не так ефективно, як квадратичне сито в цілому, але, здається, його легше здійснити.


Після того, як ви вирішили розділити число на два фактори, ось найшвидший алгоритм, про який я можу придумати, щоб знайти найбільший простий множник числа:

Створіть чергу пріоритетів, яка спочатку зберігає саме число. Кожною ітерацією ви вилучаєте найбільшу кількість із черги та намагаєтесь розділити її на два фактори (звичайно, не дозволяючи 1 бути одним із цих факторів). Якщо цей крок не вдасться, номер є простим, і ви отримаєте свою відповідь! Інакше ви додасте два фактори до черги і повторіть.


3
Pollard rho і метод еліптичної кривої набагато краще позбутися від малих простих факторів вашого числа, ніж квадратичне сито. QS має приблизно однаковий час виконання незалежно від кількості. Який підхід швидше залежить від того, який ваш номер; Швидкісні показники швидше розбиватимуть важкофакторні числа, в той час як rho та ECM швидше розбиватимуть числа, що легко фактуруються.
tmyklebu

Дякуємо за пропозицію квадратичної варіації. Мені потрібно було реалізувати це для одного з моїх клієнтів, початкова версія, яку я придумала, була чимось узгодженим із тим, що запропонував @mercutio у своєму запитанні. Квадратне рішення - це те, що зараз працює на інструменті мого клієнта на math.tools/calculator/prime-factors .
дорс

Якщо існує ефективний спосіб вирішення цієї проблеми, чи не означає це, що веб-шифрування не є безпечним?
BKSpurgeon

141

Ось найкращий алгоритм, про який я знаю (в Python)

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)гіршому випадку (коли вхід є простим числом).

EDIT:
Нижче наведена 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це прем'єр-міністр)
Шелдон Л. Купер

16
Легко зробити це O (sqrt (n)), ви просто зупиняєте цикл, коли d * d> n, і якщо n> 1 в цей момент, то його значення слід додати до списку простих факторів.
Сумуду Фернандо

5
Чи є для цього назва?
Прогноз

11
оскільки 2 є єдиним рівним простим числом, тож замість того, щоб додавати 1 кожен раз, ви можете ітератувати окремо для d = 2, а потім збільшити його на 1, а потім від d = 3 далі ви можете збільшити на 2., то це зменшить число ітерацій ... :)
tailor_raj

18

Моя відповідь заснована на триптиху , але в цьому значно покращиться. Він ґрунтується на тому, що за межами 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 приймає лише ті значення між 1 і 29, які не поділяються на 2,3 або 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)
Надер Ганбарі

8

JavaScript-код:

'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, але також різний. У цьому прикладі список або словник не використовуються. Код написаний на Ruby

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, або ...; Насправді набагато ефективніше обмежувати лише перевірку простих чи інших алгоритмів.
виграти

6
+1, щоб компенсувати wnoise, який я вважаю неправильним. Спроба розділити на 4 трапиться лише один раз і негайно зазнає невдачі. Я не думаю, що це гірше, ніж вилучити 4 із якогось списку кандидатів, і це, звичайно, швидше, ніж заздалегідь знайти всі праймери.
Триптих

2
@Beowulf. Спробуйте запустити цей код, перш ніж проголосувати. Він повертає основні фактори; ви просто не розумієте алгоритм.
Триптих

3
код працює нормально, але повільний, якщо вхідне число є простим. Я б також пробіг до площі та збільшення на 2. Це може бути занадто повільним для дуже великих чисел.
blabla999

4
blabla999 - це точно так. Приклад - 1234567898766700 = 2 * 2 * 5 * 5 * 12345678987667. Коли ми досягли currFactor = 3513642, ми знаємо, що 12345678987667 є простим, і мусимо повернути це як відповідь. Натомість цей код буде продовжувати перерахування до самого 12345678987667. Це 3,513,642x повільніше, ніж потрібно.
Буде Несс

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 099? воно теж повинно бігати в очі. Робить це?
Буде Нісс

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 опій займає одну секунду, 10 ^ 12 займе 100 секунд. Але насправді потрібні лише 10 ^ 6 ітерацій, і якщо 10 ^ 10 опі зайняти секунду, 10 ^ 6 знадобиться 1/10 000-ї секунди.
Буде Несс

1
Тому що я не розумів (10 ^ 12 + 39) - це просте число, яке я роблю зараз. Я розумію саме те, що ти кажеш.
the_prole

1
Гаразд, ви можете змінити свій код, щоб не було такого великого уповільнення для прайменів: якщо n = a b і a <= b, то a a <= b a = n, тобто a <= n . І якщо ми досягли + 1, то n - це, безумовно, прем'єр. (пінг мені, якщо ви редагуєте свою відповідь, щоб це включити).
Буде Несс

1
що відбувається коли long n = 2*1000000000039L? Це працює так швидко, як слід? (також ви можете спростити код за допомогою return;оператора?). (якщо ви хочете, щоб я перестала вас підштовхувати, просто скажіть так;))
Буде Несс

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)

Є кілька модульних тестів, які є чудовими, оскільки n ніколи не можна розділити на 6, якщо всі фактори 2 і 3 були усунені. Ви можете дозволити лише праймери для 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

Я використовую алгоритм, який продовжує ділити число за чинним основним фактором.

Моє рішення в python 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?
Буде Несс

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

але чи не намагатиметься це розділити на всі парні числа?
Янус Троельсен

0

Наведений нижче алгоритм C ++ не найкращий, але він працює для чисел, що перевищують мільярд, і досить швидко

#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

Знайшов це рішення в Інтернеті "Джеймс Ван"

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. Одна була заснована на ситі, а одна - на наступному:

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 не може. Сито використовує безліч операцій, викреслюючи всі складені числа.

Зауважте також, що мої фактори розподілу при їх виявленні зменшують простір, який необхідно перевірити.


це те, що я сказав, але мене проголосували :( Я думаю, проблема полягає в тому, що якщо число має дійсно великий простий коефіцієнт (такий, як він сам), то цей метод повинен провести цикл аж до цієї кількості. У багатьох випадках однак цей метод є досить ефективним.
nickf

Читання назад через ваше - це те саме, але перша частина вашого заплутана.
Лорен Печтел,

Спробуйте, що за цим номером 143816789988504044536402352738195137863656439, дайте мені знати, наскільки це ефективно ...
MichaelICE

-1

Обчисліть список, у якому спочатку зберігаються прості числа, наприклад, 2 3 5 7 11 13 ...

Кожен раз, коли ви просте множення числа, використовуйте реалізацію за триптихом, але повторюйте цей список простих чисел, а не натуральні цілі числа.


-1

З Java:

Для 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 ви можете використовувати сито Ератостена або сито Аткінса або що завгодно, але саме по собі сито не знайде для вас найбільшого основного чинника. (Ось чому я не вибрав посаду SQLMenace як офіційну відповідь ...)


1
Чи не потрібно робити пробний факторинг, щоб визначити, чи є простим числом (крок 2)? Також розглянемо пошук найбільшого основного коефіцієнта 15. Праймерів до sqrt (15) є 2 і 3; але найбільший основний коефіцієнт - 5, чи не так? Аналогічно з 20.
Джонатан Леффлер

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

Це не відповідь на запитання. ;-) Питання полягало у тому, щоб знайти найбільший основний фактор, а не перевірити наявність первинності.
Ганс-Пітер Штерр

Набагато ефективніше ініціалізувати цикл як (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();
 }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.