Який найефективніший спосіб знайти всі множники числа в Python?


142

Чи може хтось пояснити мені ефективний спосіб пошуку всіх факторів числа в Python (2.7)?

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


3
Я не знаю пітона. Але ця сторінка може бути для вас корисною en.wikipedia.org/wiki/Integer_factorization
Стан

3
Як щодо використання primefac? pypi.python.org/pypi/primefac
Зубо

Відповіді:


265
from functools import reduce

def factors(n):    
    return set(reduce(list.__add__, 
                ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))

Це дуже швидко поверне всі фактори n.

Чому квадратний корінь як верхня межа?

sqrt(x) * sqrt(x) = x. Отже, якщо два фактори однакові, вони обидва мають квадратний корінь. Якщо ви зробите один фактор більшим, ви повинні зробити інший фактор меншим. Це означає, що один з двох завжди буде меншим або рівним sqrt(x), тому вам потрібно лише шукати до цього моменту, щоб знайти один з двох відповідних факторів. Потім ви можете використовувати x / fac1для отримання fac2.

reduce(list.__add__, ...)Приймають маленькі списки [fac1, fac2]і поєднуючи їх разом в один довгий список.

В [i, n/i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0повертається пара факторів , якщо залишок при поділі nна менший дорівнює нулю (це не потрібно , щоб перевірити більше один теж, він просто отримує , що при розподілі nна один менше.)

set(...)Зовні позбавляються від дублікатів, яка буває тільки для ідеальних квадратів. Бо n = 4це повернеться 2двічі, тому setпозбудеться одного з них.


1
Я скопіював це із списку алгоритмів на моєму комп’ютері, все, що я робив, було інкапсулювати sqrt- це, мабуть, раніше, ніж люди по-справжньому думали про підтримку Python 3. Я думаю, що сайт, який я отримав, спробував це, __iadd__і це було швидше . Я, здається, пам’ятаю щось про x**0.5те, щоб пройти швидше, ніж sqrt(x)в якийсь момент, - і це більш безглуздо.
agf

7
Здається, що на 15% швидше, якщо я if not n % iзамість цього використовуюif n % i == 0
dansalmo

3
@sthzg Ми хочемо, щоб він повернув ціле число, а не float, і на Python 3 /поверне float, навіть якщо обидва аргументи є цілими числами, і вони точно поділяються, тобто 4 / 2 == 2.0ні 2.
agf

7
Я знаю, що це старе питання, але в Python 3.x вам потрібно додати, from functools import reduceщоб зробити цю роботу.
анонімний

5
@unseen_rider: Це не правильно. Чи можете ви надати що-небудь, щоб підкріпити це?
Ри-

55

Рішення, представлене @agf, є чудовим, але можна домогтися ~ 50% швидшого часу запуску для довільного непарного числа, перевіривши парність. Оскільки коефіцієнти непарного числа завжди непарні самі, їх не потрібно перевіряти при роботі з непарними числами.

Я щойно почав самостійно розгадувати загадки Project Euler . У деяких проблемах перевірка дільником викликається всередині двох вкладених forциклів, тому виконання цієї функції є суттєвим.

Поєднуючи цей факт з відмінним рішенням agf, я закінчив цю функцію:

from math import sqrt
def factors(n):
        step = 2 if n%2 else 1
        return set(reduce(list.__add__,
                    ([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))

Однак у малих числах (~ <100) додаткові накладні витрати від цієї зміни можуть спричинити зайняття функції довше.

Я провів кілька тестів, щоб перевірити швидкість. Нижче наведено використаний код. Щоб створити різні сюжети, я відповідним чином змінив X = range(1,100,1).

import timeit
from math import sqrt
from matplotlib.pyplot import plot, legend, show

def factors_1(n):
    step = 2 if n%2 else 1
    return set(reduce(list.__add__,
                ([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))

def factors_2(n):
    return set(reduce(list.__add__,
                ([i, n//i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0)))

X = range(1,100000,1000)
Y = []
for i in X:
    f_1 = timeit.timeit('factors_1({})'.format(i), setup='from __main__ import factors_1', number=10000)
    f_2 = timeit.timeit('factors_2({})'.format(i), setup='from __main__ import factors_2', number=10000)
    Y.append(f_1/f_2)
plot(X,Y, label='Running time with/without parity check')
legend()
show()

X = діапазон (1,100,1) X = діапазон (1,100,1)

Тут немає суттєвої різниці, але при більшій кількості перевага очевидна:

X = діапазон (1,100000,1000) (лише непарні числа) X = діапазон (1,100000,1000) (лише непарні числа)

X = діапазон (2100000,100) (лише парні числа) X = діапазон (2100000,100) (лише парні числа)

X = діапазон (1,100000,1001) (змінний паритет) X = діапазон (1,100000,1001) (змінний паритет)


28

відповідь AGF дійсно досить класна. Я хотів побачити, чи можу я його переписати, щоб уникнути використання reduce(). Ось що я придумав:

import itertools
flatten_iter = itertools.chain.from_iterable
def factors(n):
    return set(flatten_iter((i, n//i) 
                for i in range(1, int(n**0.5)+1) if n % i == 0))

Я також спробував версію, яка використовує складні функції генератора:

def factors(n):
    return set(x for tup in ([i, n//i] 
                for i in range(1, int(n**0.5)+1) if n % i == 0) for x in tup)

Я приурочив її до обчислення:

start = 10000000
end = start + 40000
for n in range(start, end):
    factors(n)

Я запустив його один раз, щоб Python склав його, потім тричі під командою time (1) запустив найкращий час.

  • скоротити версію: 11,58 секунди
  • версія itertools: 11,49 секунди
  • хитра версія: 11,12 секунди

Зауважте, що версія itertools будує кортеж і передає його flatten_iter (). Якщо я замінюю код для створення списку, він трохи сповільнюється:

  • версія iterools (список): 11,62 секунди

Я вважаю, що версія хитрої функції генератора є найшвидшою в Python. Але це не набагато швидше, ніж версія зменшення, приблизно на 4% швидше на основі моїх вимірів.


2
ви можете спростити "хитру версію" (видалити непотрібне for tup in):factors = lambda n: {f for i in range(1, int(n**0.5)+1) if n % i == 0 for f in [i, n//i]}
jfs

11

Альтернативний підхід до відповіді AGF:

def factors(n):    
    result = set()
    for i in range(1, int(n ** 0.5) + 1):
        div, mod = divmod(n, i)
        if mod == 0:
            result |= {i, div}
    return result

1
Чи можете ви пояснити діву, частину мода?
Аднан

3
divmod (x, y) повертає ((xx% y) / y, x% y), тобто коефіцієнт і залишок ділення.
c4757p

Це не справляється з повторюваними факторами - спробуйте, наприклад, 81.
phkahler

Ваша відповідь ясніша, тож я зміг обмацувати її досить просто, щоб неправильно зрозуміти. Я думав про основну факторизацію, де ви хочете викликати декілька 3-х. Це повинно бути добре, оскільки саме про це вимагала ОП.
phkahler

Я зібрав все в один рядок, тому що відповідь AGF так і зробила. Мені було цікаво побачити, чи reduce()було значно швидше, тому я майже все робив, крім reduce()частини, так само, як це робив AGF. Для читабельності було б непогано побачити виклик функції, is_even(n)а не вираз подібний n % 2 == 0.
steveha

9

Ось альтернатива рішення @ agf, яке реалізує той же алгоритм у більш пітонічному стилі:

def factors(n):
    return set(
        factor for i in range(1, int(n**0.5) + 1) if n % i == 0
        for factor in (i, n//i)
    )

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


7

У SymPy існує алгоритм міцності в галузі, який називається factorint :

>>> from sympy import factorint
>>> factorint(2**70 + 3**80) 
{5: 2,
 41: 1,
 101: 1,
 181: 1,
 821: 1,
 1597: 1,
 5393: 1,
 27188665321L: 1,
 41030818561L: 1}

Це зайняло менше хвилини. Він перемикається серед коктейлів методів. Дивіться документацію, пов'язану вище.

Враховуючи всі найважливіші фактори, всі інші фактори можна побудувати легко.


Зауважте, що навіть якщо прийнятої відповіді було дозволено працювати досить довго (тобто цілу вічність), щоб підрахувати вказане вище число, для деяких великих чисел воно буде невдалим, такий наступний приклад. Це пов’язано з неохайністю int(n**0.5). Наприклад, коли n = 10000000000000079**2, у нас є

>>> int(n**0.5)
10000000000000078L

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


2
Він не знаходить усіх дільників, а лише основні фактори, тому це насправді не відповідь. Ви повинні показати, як можна побудувати всі інші фактори, а не просто сказати, що це просто! До речі, sympy.divisors може краще відповісти на це питання.
Колін Пітрат

І зауважте, що sympy.divisors не набагато швидше прийнятого рішення.
Колін Пітрат

@ColinPitrat: Я сумніваюся, що sympy.divisorsце не набагато швидше, зокрема для чисел, які мають кілька дільників. Отримали якісь орієнтири?
Ри-

@Ry Я зробив це, коли я написав цей коментар рік тому. На написання потрібне 2 хв, тому сміливо перевіряйте.
Колін Пітрат

3
@ColinPitrat: Перевірено. Як і очікувалося, прийнята відповідь приблизно з тією ж швидкістю, що і sympy.divisorsдля 100 000, і повільніше для будь-якого вищого (коли швидкість насправді має значення). (І, звичайно, sympy.divisorsпрацює на числах на кшталт 10000000000000079**2.)
Ри-

7

Для n до 10 ** 16 (можливо, навіть трохи більше), ось швидке чисте рішення Python 3.6,

from itertools import compress

def primes(n):
    """ Returns  a list of primes < n for n > 2 """
    sieve = bytearray([True]) * (n//2)
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = bytearray((n-i*i-1)//(2*i)+1)
    return [2,*compress(range(3,n,2), sieve[1:])]

def factorization(n):
    """ Returns a list of the prime factorization of n """
    pf = []
    for p in primeslist:
      if p*p > n : break
      count = 0
      while not n % p:
        n //= p
        count += 1
      if count > 0: pf.append((p, count))
    if n > 1: pf.append((n, 1))
    return pf

def divisors(n):
    """ Returns an unsorted list of the divisors of n """
    divs = [1]
    for p, e in factorization(n):
        divs += [x*p**k for k in range(1,e+1) for x in divs]
    return divs

n = 600851475143
primeslist = primes(int(n**0.5)+1) 
print(divisors(n))

6

Подальше вдосконалення рішення афг та еріксуна. Наступний фрагмент коду повертає відсортований список усіх факторів, не змінюючи асимптотичну складність часу виконання:

    def factors(n):    
        l1, l2 = [], []
        for i in range(1, int(n ** 0.5) + 1):
            q,r = n//i, n%i     # Alter: divmod() fn can be used.
            if r == 0:
                l1.append(i) 
                l2.append(q)    # q's obtained are decreasing.
        if l1[-1] == l2[-1]:    # To avoid duplication of the possible factor sqrt(n)
            l1.pop()
        l2.reverse()
        return l1 + l2

Ідея: Замість використання функції list.sort () для отримання відсортованого списку, який надає nlog (n) складність; Набагато швидше використовувати list.reverse () на l2, що приймає O (n) складність. (Ось так робиться пітон.) Після l2.reverse (), l2 може бути доданий до l1 для отримання відсортованого списку факторів.

Зауважте, l1 містить i -s, які збільшуються. l2 містить q -s, які зменшуються. У цьому причина використання вищезгаданої ідеї.


Досить впевнений list.reverse, що O (n) не O (1), не те, що це змінює загальну складність.
agf

Так, правильно. Я зробив помилку. Повинно бути O (n). (Я оновив відповідь зараз до правильної)
Pranjal Mittal

Це приблизно в 2 рази повільніше, ніж рішення @ steveha або @ agf.
jfs

Ви можете отримати невелике (2-3%) покращення швидкості, повернувшись, l1 + l2.reversed()а не перевернувши список на місці.
Ракурай

6

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

def factors(n):
    results = set()
    for i in xrange(1, int(math.sqrt(n)) + 1):
        if n % i == 0:
            results.add(i)
            results.add(int(n/i))
    return results

Як написано, вам доведеться імпортувати математику для тестування, але заміна math.sqrt (n) на n **. 5 повинна працювати так само добре. Я не турбуюсь витрачати час на перевірку дублікатів, оскільки копії не можуть існувати в наборі незалежно.


Чудові речі! Якщо ви поставите int (math.sqrt (n)) + 1 поза циклу for, вам слід отримати трохи більше продуктивності, оскільки не доведеться повторно обчислювати його кожною ітерацією циклу for
Tristan Forward

3
@TristanForward: Це не так, як петлі працюють у Python. xrange(1, int(math.sqrt(n)) + 1)оцінюється один раз.
Ри-

5

Ось ще один заступник без зменшення, який добре справляється з великою кількістю. Він використовується sumдля вирівнювання списку.

def factors(n):
    return set(sum([[i, n//i] for i in xrange(1, int(n**0.5)+1) if not n%i], []))

1
Це не так, це зайвий квадратичний час. Не використовуйте sumта reduce(list.__add__)не вирівнюйте список.
juanpa.arrivillaga

4

Не забудьте взяти число більше, ніж sqrt(number_to_factor)для незвичайних чисел, таких як 99, у яких 3 * 3 * 11 і floor sqrt(99)+1 == 10.

import math

def factor(x):
  if x == 0 or x == 1:
    return None
  res = []
  for i in range(2,int(math.floor(math.sqrt(x)+1))):
    while x % i == 0:
      x /= i
      res.append(i)
  if x != 1: # Unusual numbers
    res.append(x)
  return res

1
Він не виробляє всіх факторів числа. Він обчислює прості множники числа, наприклад, для x=8очікуваного:, [1, 2, 4, 8]отримано:[2, 2, 2]
jfs

11 знайдено, коли 9 обчислюється в коді, поданому @agf. `i = 9 -> 99% 9 == 0 -> 9 і 99/9 = 11 додається.
Стейнар Ліма

4

Найпростіший спосіб знаходження факторів числа:

def factors(x):
    return [i for i in range(1,x+1) if x%i==0]

2

Ось приклад, якщо ви хочете використовувати число простих ліній, щоб пройти набагато швидше. Ці списки легко знайти в Інтернеті. Я додав коментарі до коду.

# http://primes.utm.edu/lists/small/10000.txt
# First 10000 primes

_PRIMES = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 
        31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 
        73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 
        127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 
        179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 
        233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 
        283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 
        353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 
        419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 
        467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 
        547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 
        607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 
        661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 
        739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 
        811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 
        877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 
        947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 
# Mising a lot of primes for the purpose of the example
)


from bisect import bisect_left as _bisect_left
from math import sqrt as _sqrt


def get_factors(n):
    assert isinstance(n, int), "n must be an integer."
    assert n > 0, "n must be greather than zero."
    limit = pow(_PRIMES[-1], 2)
    assert n <= limit, "n is greather then the limit of {0}".format(limit)
    result = set((1, n))
    root = int(_sqrt(n))
    primes = [t for t in get_primes_smaller_than(root + 1) if not n % t]
    result.update(primes)  # Add all the primes factors less or equal to root square
    for t in primes:
        result.update(get_factors(n/t))  # Add all the factors associted for the primes by using the same process
    return sorted(result)


def get_primes_smaller_than(n):
    return _PRIMES[:_bisect_left(_PRIMES, n)]

Я створив проект на Github: github.com/Pierre-Thibault/Factor .
П'єр Тібо

2

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

def factors(n):
    '''
    return prime factors and multiplicity of n
    n = p0^e0 * p1^e1 * ... * pk^ek encoded as
    res = [(p0, e0), (p1, e1), ..., (pk, ek)]
    '''

    res = []

    # get rid of all the factors of 2 using bit shifts
    mult = 0
    while not n & 1:
        mult += 1
        n >>= 1
    if mult != 0:
        res.append((2, mult))

    limit = round(sqrt(n))
    test_prime = 3
    while test_prime <= limit:
        mult = 0
        while n % test_prime == 0:
            mult += 1
            n //= test_prime
        if mult != 0:
            res.append((test_prime, mult))
            if n == 1:              # only useful if ek >= 3 (ek: multiplicity
                break               # of the last prime) 
            limit = round(sqrt(n))  # adjust the limit
        test_prime += 2             # will often not be prime...
    if n != 1:
        res.append((n, 1))
    return res

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

це python3; поділ //має бути єдиним, що потрібно адаптувати для python 2 (додати from __future__ import division).


1

Використання set(...)робить код трохи повільнішим і дійсно необхідний лише для перевірки квадратного кореня. Ось моя версія:

def factors(num):
    if (num == 1 or num == 0):
        return []
    f = [1]
    sq = int(math.sqrt(num))
    for i in range(2, sq):
        if num % i == 0:
            f.append(i)
            f.append(num/i)
    if sq > 1 and num % sq == 0:
        f.append(sq)
        if sq*sq != num:
            f.append(num/sq)
    return f

The if sq*sq != num:Умова необхідно для чисел , як 12, де квадратний корінь не є цілим числом, але пів квадратного кореня є фактором.

Зауважте, що ця версія не повертає номер сам, але це легко виправити, якщо ви цього хочете. Вихід також не відсортований.

Я приуротив його до 10000 разів на всіх числах 1-200 і 100 разів на всіх номерах 1-5000. Він перевершує всі інші перевірені нами версії, включаючи розчини дансальмо, Джейсона Шорна, оксрокові, agf, стевеха та еріксун, хоча оксрок - це найбільш близький.


1

ваш максимальний коефіцієнт не більше вашого числа, тому, скажімо

def factors(n):
    factors = []
    for i in range(1, n//2+1):
        if n % i == 0:
            factors.append (i)
    factors.append(n)

    return factors

voilá!


1
 import math

    '''
    I applied finding prime factorization to solve this. (Trial Division)
    It's not complicated
    '''


    def generate_factors(n):
        lower_bound_check = int(math.sqrt(n))  # determine lowest bound divisor range [16 = 4]
        factors = set()  # store factors
        for divisors in range(1, lower_bound_check + 1):  # loop [1 .. 4]
            if n % divisors == 0:
                factors.add(divisors)  # lower bound divisor is found 16 [ 1, 2, 4]
                factors.add(n // divisors)  # get upper divisor from lower [ 16 / 1 = 16, 16 / 2 = 8, 16 / 4 = 4]
        return factors  # [1, 2, 4, 8 16]


    print(generate_factors(12)) # {1, 2, 3, 4, 6, 12} -> pycharm output

 Pierre Vriens hopefully this makes more sense. this is an O(nlogn) solution. 

0

Використовуйте щось таке просте, як наступне розуміння списку, зазначивши, що нам не потрібно тестувати 1 і число, яке ми намагаємося знайти:

def factors(n):
    return [x for x in range(2, n//2+1) if n%x == 0]

Посилаючись на використання квадратного кореня, скажімо, ми хочемо знайти коефіцієнти 10. Ціла частина, sqrt(10) = 4отже, range(1, int(sqrt(10))) = [1, 2, 3, 4]і тестування до 4 явно пропускає 5.

Якщо я не пропускаю чогось, я б запропонував, якщо ви повинні зробити це таким чином, використовуючи int(ceil(sqrt(x))). Звичайно, це спричиняє багато непотрібних дзвінків до функцій.


Проблема цього рішення полягає в тому, що він перевіряє багато чисел, які, можливо, не можуть бути чинниками - і він перевіряє вищі з кожної пари факторів окремо, коли ви вже знаєте, що це фактор після знаходження меншої пари пар факторів.
agf

1
@JasonSchorn: Коли ви знайдете 2, ви відразу знаєте, що 10/2 = 5 - це також дільник, не потрібно перевіряти 5 окремо! :)
Moberg

0

Я думаю, що для читабельності та швидкості рішення @ oxrock найкраще, тому ось переписаний код для python 3+:

def num_factors(n):
    results = set()
    for i in range(1, int(n**0.5) + 1):
        if n % i == 0: results.update([i,int(n/i)])
    return results

0

Я був дуже здивований, коли побачив це питання, що ніхто не використовував numpy, навіть коли numpy набагато швидше, ніж петлі python. Реалізувавши рішення @ agf з numpy, і вийшло в середньому на 8 разів швидше . Я вірю, що якби ти впровадив деякі інші рішення в нуме, ти можеш отримати дивовижні часи.

Ось моя функція:

import numpy as np
def b(n):
    r = np.arange(1, int(n ** 0.5) + 1)
    x = r[np.mod(n, r) == 0]
    return set(np.concatenate((x, n / x), axis=None))   

Зауважте, що числа осі x не є входом до функцій. Вхід до функцій - 2 до числа на осі х мінус 1. Тож де десять - вхід буде 2 ** 10-1 = 1023

Результати тесту на ефективність використання numpy замість циклів.


1
Якщо ви збираєтеся використовувати бібліотеку, можливо, це зробить правильним: SymPy, як видно з відповіді Євгена Сергєєва.
Ри-

0
import 'dart:math';
generateFactorsOfN(N){
  //determine lowest bound divisor range
  final lowerBoundCheck = sqrt(N).toInt();
  var factors = Set<int>(); //stores factors
  /**
   * Lets take 16:
   * 4 = sqrt(16)
   * start from 1 ...  4 inclusive
   * check mod 16 % 1 == 0?  set[1, (16 / 1)]
   * check mod 16 % 2 == 0?  set[1, (16 / 1) , 2 , (16 / 2)]
   * check mod 16 % 3 == 0?  set[1, (16 / 1) , 2 , (16 / 2)] -> unchanged
   * check mod 16 % 4 == 0?  set[1, (16 / 1) , 2 , (16 / 2), 4, (16 / 4)]
   *
   *  ******************* set is used to remove duplicate
   *  ******************* case 4 and (16 / 4) both equal to 4
   *  return factor set<int>.. this isn't ordered
   */

  for(var divisor = 1; divisor <= lowerBoundCheck; divisor++){
    if(N % divisor == 0){
      factors.add(divisor);
      factors.add(N ~/ divisor); // ~/ integer division 
    }
  }
  return factors;
}

Майже весь алгоритм тут обмежується діапазоном до числа * .5, але насправді цей діапазон значно менший. його фактично sqrt числа. якщо у нас є нижній дільник, ми можемо легко отримати його верхній. оскільки його просто число / дільник. для 16 я отримую 4 для sqrt, тоді цикл від 1 до 4. оскільки 2 - нижній граничний дільник на 16, ми беремо 16/2, щоб отримати 8., якщо у нас є 1, щоб отримати 16 є (16/1). Я придумав це, дізнавшись про основну факторизацію, тому я не знаю, чи вона опублікована деінде, але вона працює навіть для великої кількості. Я можу надати рішення пітона.
Танганг Атанга

-4

Я вважаю, що це найпростіший спосіб зробити це:

    x = 23

    i = 1
    while i <= x:
      if x % i == 0:
        print("factor: %s"% i)
      i += 1

Ваша відповідь, даючи правильний результат, дуже неефективна. Погляньте на прийняту відповідь. Пояснення, як воно вирішує проблему, завжди допомагає відповіді бути кориснішою.
Нік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.