简体   繁体   English

在 Python 中找到一个数的所有因子的最有效方法是什么?

[英]What is the most efficient way of finding all the factors of a number in Python?

Can someone explain to me an efficient way of finding all the factors of a number in Python (2.7)?有人可以向我解释一种找到 Python (2.7) 中数字的所有因子的有效方法吗?

I can create an algorithm to do this, but I think it is poorly coded and takes too long to produce a result for a large number.我可以创建一个算法来执行此操作,但我认为它的编码很差,并且需要很长时间才能为大量结果生成结果。

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

This will return all of the factors, very quickly, of a number n .这将很快返回数字n所有因子。

Why square root as the upper limit?为什么平方根作为上限?

sqrt(x) * sqrt(x) = x . sqrt(x) * sqrt(x) = x So if the two factors are the same, they're both the square root.因此,如果两个因数相同,则它们都是平方根。 If you make one factor bigger, you have to make the other factor smaller.如果您将一个因素放大,则必须使另一个因素变小。 This means that one of the two will always be less than or equal to sqrt(x) , so you only have to search up to that point to find one of the two matching factors.这意味着两者之一将始终小于或等于sqrt(x) ,因此您只需搜索到该点即可找到两个匹配因子之一。 You can then use x / fac1 to get fac2 .然后,您可以使用x / fac1得到fac2

The reduce(list.__add__, ...) is taking the little lists of [fac1, fac2] and joining them together in one long list. reduce(list.__add__, ...)[fac1, fac2]的小列表合并到一个长列表中。

The [i, n/i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0 returns a pair of factors if the remainder when you divide n by the smaller one is zero (it doesn't need to check the larger one too; it just gets that by dividing n by the smaller one.) [i, n/i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0如果将n除以较小的余数时的余数[i, n/i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0返回一对因子(它也不需要检查较大的;它只是通过将n除以较小的来获得。)

The set(...) on the outside is getting rid of duplicates, which only happens for perfect squares.外面的set(...)正在摆脱重复,这只会发生在完美的正方形上。 For n = 4 , this will return 2 twice, so set gets rid of one of them.对于n = 4 ,这将返回2两次,因此set摆脱了其中之一。

The solution presented by @agf is great, but one can achieve ~50% faster run time for an arbitrary odd number by checking for parity. @agf 提出的解决方案很棒,但是通过检查奇偶校验可以将任意奇数的运行时间缩短约 50%。 As the factors of an odd number always are odd themselves, it is not necessary to check these when dealing with odd numbers.由于奇数的因数本身总是奇数,因此在处理奇数时无需检查这些。

I've just started solving Project Euler puzzles myself.我刚刚开始自己​​解决Project Euler难题。 In some problems, a divisor check is called inside two nested for loops, and the performance of this function is thus essential.在某些问题中,在两个嵌套的for循环中调用除数检查,因此该函数的性能至关重要。

Combining this fact with agf's excellent solution, I've ended up with this function:将此事实与 agf 的出色解决方案相结合,我最终得到了此功能:

from functools import reduce
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)))

However, on small numbers (~ < 100), the extra overhead from this alteration may cause the function to take longer.但是,对于较小的数字 (~ < 100),此更改带来的额外开销可能会导致函数花费更长的时间。

I ran some tests in order to check the speed.我进行了一些测试以检查速度。 Below is the code used.下面是使用的代码。 To produce the different plots, I altered the X = range(1,100,1) accordingly.为了生成不同的图,我相应地更改了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 = range(1,100,1) X = 范围(1,100,1)X = 范围(1,100,1)

No significant difference here, but with bigger numbers, the advantage is obvious:这里没有显着差异,但数字越大,优势就很明显:

X = range(1,100000,1000) (only odd numbers) X = range(1,100000,1000)(仅奇数)X = range(1,100000,1000)(仅奇数)

X = range(2,100000,100) (only even numbers) X = range(2,100000,100)(仅偶数)X = range(2,100000,100)(仅偶数)

X = range(1,100000,1001) (alternating parity) X = range(1,100000,1001)(交替奇偶校验) X = range(1,100000,1001)(交替奇偶校验)

agf's answer is really quite cool. agf 的回答真的很酷。 I wanted to see if I could rewrite it to avoid using reduce() .我想看看是否可以重写它以避免使用reduce() This is what I came up with:这就是我想出的:

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

I also tried a version that uses tricky generator functions:我还尝试了一个使用棘手的生成器函数的版本:

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)

I timed it by computing:我通过计算来计时:

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

I ran it once to let Python compile it, then ran it under the time(1) command three times and kept the best time.我跑了一次让Python编译,然后在time(1)命令下跑了3次,保持最佳时间。

  • reduce version: 11.58 seconds减少版本:11.58 秒
  • itertools version: 11.49 seconds itertools 版本:11.49 秒
  • tricky version: 11.12 seconds棘手版本:11.12 秒

Note that the itertools version is building a tuple and passing it to flatten_iter().请注意,itertools 版本正在构建一个元组并将其传递给 flatten_iter()。 If I change the code to build a list instead, it slows down slightly:如果我更改代码来构建列表,它会稍微减慢速度:

  • iterools (list) version: 11.62 seconds iterools(列表)版本:11.62 秒

I believe that the tricky generator functions version is the fastest possible in Python.我相信棘手的生成器函数版本是 Python 中最快的。 But it's not really much faster than the reduce version, roughly 4% faster based on my measurements.但它并不比 reduce 版本快多少,根据我的测量,大约快 4%。

There is an industry-strength algorithm in SymPy called factorint : 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}

This took under a minute.这花了不到一分钟。 It switches among a cocktail of methods.它在多种方法之间切换。 See the documentation linked above.请参阅上面链接的文档。

Given all the prime factors, all other factors can be built easily.给定所有主要因素,所有其他因素都可以轻松构建。


Note that even if the accepted answer was allowed to run for long enough (ie an eternity) to factor the above number, for some large numbers it will fail, such the following example.请注意,即使允许接受的答案运行足够长的时间(即永恒)来分解上述数字,对于某些大数字,它也会失败,例如以下示例。 This is due to the sloppy int(n**0.5) .这是由于草率的int(n**0.5) For example, when n = 10000000000000079**2 , we have例如,当n = 10000000000000079**2 ,我们有

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

Since 10000000000000079 is a prime , the accepted answer's algorithm will never find this factor.由于10000000000000079 是一个质数,接受的答案的算法永远不会找到这个因素。 Note that it's not just an off-by-one;请注意,这不仅仅是一对一的; for larger numbers it will be off by more.对于较大的数字,它会减少更多。 For this reason it's better to avoid floating-point numbers in algorithms of this sort.出于这个原因,最好避免在此类算法中使用浮点数。

Here's an alternative to @agf's solution which implements the same algorithm in a more pythonic style:这是@agf 解决方案的替代方案,它以更pythonic 的风格实现了相同的算法:

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

This solution works in both Python 2 and Python 3 with no imports and is much more readable.此解决方案适用于 Python 2 和 Python 3,无需导入,并且更具可读性。 I haven't tested the performance of this approach, but asymptotically it should be the same, and if performance is a serious concern, neither solution is optimal.我还没有测试过这种方法的性能,但渐近地它应该是一样的,如果性能是一个严重的问题,那么两种解决方案都不是最佳的。

For n up to 10**16 (maybe even a bit more), here is a fast pure Python 3.6 solution,对于高达 10**16(甚至更多)的 n,这是一个快速的纯 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))

An alternative approach to agf's answer: 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

The simplest way of finding factors of a number:求一个数的因数的最简单方法:

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

I've tried most of these wonderful answers with timeit to compare their efficiency versus my simple function and yet I constantly see mine outperform those listed here.我已经用 timeit 尝试了大多数这些精彩的答案,以将它们的效率与我的简单功能进行比较,但我经常看到我的性能优于此处列出的那些。 I figured I'd share it and see what you all think.我想我会分享它,看看大家的想法。

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

As it's written you'll have to import math to test, but replacing math.sqrt(n) with n**.5 should work just as well.正如它所写的那样,您必须导入数学来进行测试,但是将 math.sqrt(n) 替换为 n**.5 应该也能正常工作。 I don't bother wasting time checking for duplicates because duplicates can't exist in a set regardless.我不想浪费时间检查重复项,因为无论如何重复项都不能存在于集合中。

Further improvement to afg & eryksun's solution.进一步改进 afg & eryksun 的解决方案。 The following piece of code returns a sorted list of all the factors without changing run time asymptotic complexity:以下代码返回所有因素的排序列表,而不会改变运行时渐近复杂度:

    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

Idea: Instead of using the list.sort() function to get a sorted list which gives nlog(n) complexity;想法:而不是使用 list.sort() 函数来获得一个排序列表,它给出了 nlog(n) 复杂度; It is much faster to use list.reverse() on l2 which takes O(n) complexity.在需要 O(n) 复杂度的 l2 上使用 list.reverse() 要快得多。 (That's how python is made.) After l2.reverse(), l2 may be appended to l1 to get the sorted list of factors. (python 就是这样制作的。)在 l2.reverse() 之后,可以将 l2 附加到 l1 以获得排序的因子列表。

Notice, l1 contains i -s which are increasing.请注意, l1 包含i -s 正在增加。 l2 contains q -s which are decreasing. l2 包含正在减少的q -s。 Thats the reason behind using the above idea.这就是使用上述想法的原因。

Here is another alternate without reduce that performs well with large numbers.这是另一种没有减少的替代方法,它在大数字上表现良好。 It uses sum to flatten the list.它使用sum来展平列表。

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

Be sure to grab the number larger than sqrt(number_to_factor) for unusual numbers like 99 which has 3*3*11 and floor sqrt(99)+1 == 10 .对于不寻常的数字,比如 99,它有 3*3*11 和floor sqrt(99)+1 == 10一定要抓住大于sqrt(number_to_factor)的数字。

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

Here is an example if you want to use the primes number to go a lot faster.如果您想使用素数来加快速度,这是一个示例。 These lists are easy to find on the internet.这些列表很容易在互联网上找到。 I added comments in the code.我在代码中添加了注释。

# 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)]

a potentially more efficient algorithm than the ones presented here already (especially if there are small prime factons in n ).一种可能比这里已经介绍的算法更有效的算法(特别是如果n有小的素n )。 the trick here is to adjust the limit up to which trial division is needed every time prime factors are found:这里的技巧是在每次找到质因数时调整需要试除的限制

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

this is of course still trial division and nothing more fancy.这当然还是试师,没什么好看的。 and therefore still very limited in its efficiency (especially for big numbers without small divisors).因此它的效率仍然非常有限(特别是对于没有小除数的大数)。

this is python3;这是python3; the division // should be the only thing you need to adapt for python 2 (add from __future__ import division ).除法//应该是您唯一需要适应 python 2 的东西( from __future__ import division添加)。

Using set(...) makes the code slightly slower, and is only really necessary for when you check the square root.使用set(...)会使代码稍微变慢,并且只有在检查平方根时才真正需要。 Here's my version:这是我的版本:

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: condition is necessary for numbers like 12, where the square root is not an integer, but the floor of the square root is a factor. if sq*sq != num:条件对于像 12 这样的数字是必要的,其中平方根不是整数,但平方根的下限是一个因子。

Note that this version doesn't return the number itself, but that is an easy fix if you want it.请注意,此版本不会返回数字本身,但如果您需要,这很容易解决。 The output also isn't sorted.输出也没有排序。

I timed it running 10000 times on all numbers 1-200 and 100 times on all numbers 1-5000.我计时它在所有数字 1-200 上运行 10000 次,在所有数字 1-5000 上运行 100 次。 It outperforms all the other versions I tested, including dansalmo's, Jason Schorn's, oxrock's, agf's, steveha's, and eryksun's solutions, though oxrock's is by far the closest.它优于我测试过的所有其他版本,包括 dansalmo、Jason Schorn、oxrock、agf、steveha 和 eryksun 的解决方案,尽管 oxrock 是迄今为止最接近的。

I was pretty surprised when I saw this question that no one used numpy even when numpy is way faster than python loops.当我看到这个问题时,我感到非常惊讶,即使 numpy 比 python 循环快得多,也没有人使用 numpy。 By implementing @agf's solution with numpy and it turned out at average 8x faster .通过使用 numpy 实施@agf 的解决方案,结果平均8 倍 I belive that if you implemented some of the other solutions in numpy you could get amazing times.我相信,如果您在 numpy 中实现了其他一些解决方案,您可以获得惊人的时间。

Here is my function:这是我的功能:

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

Notice that the numbers of the x-axis are not the input to the functions.请注意,x 轴的数字不是函数的输入。 The input to the functions is 2 to the the number on the x-axis minus 1. So where ten is the input would be 2**10-1 = 1023函数的输入是 x 轴上的数字减 1 的 2。所以输入十是 2**10-1 = 1023

使用 numpy 代替 for 循环的性能测试结果。

your max factor is not more than your number, so, let's say你的最大因素不超过你的数字,所以,让我们说

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á!瞧!

 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. 

If you don't wanna use any library, than I think so this is the easiest way to do如果您不想使用任何库,那么我认为这是最简单的方法

def factors(n):
    l=[] #emoty list
    # appending the factors in the list
    for i in range(1,n+1):
        if n%i==0:
            l.append(i)

I am an intermediate programmer.我是一名中级程序员。 So in case, If I am wrong pls correct me所以以防万一,如果我错了,请纠正我

Use something as simple as the following list comprehension, noting that we do not need to test 1 and the number we are trying to find:使用像以下列表推导这样简单的东西,注意我们不需要测试 1 和我们试图找到的数字:

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

In reference to the use of square root, say we want to find factors of 10. The integer portion of the sqrt(10) = 4 therefore range(1, int(sqrt(10))) = [1, 2, 3, 4] and testing up to 4 clearly misses 5.关于平方根的使用,假设我们要找到 10 的因数。 sqrt(10) = 4的整数部分因此range(1, int(sqrt(10))) = [1, 2, 3, 4]并且测试多达 4 次显然错过了 5 次。

Unless I am missing something I would suggest, if you must do it this way, using int(ceil(sqrt(x))) .除非我遗漏了一些我建议的东西,如果你必须这样做,使用int(ceil(sqrt(x))) Of course this produces a lot of unnecessary calls to functions.当然,这会产生大量不必要的函数调用。

I think for readability and speed @oxrock's solution is the best, so here is the code rewritten for python 3+:我认为为了可读性和速度@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

loop until you find a duplicate in x or v of the tuple where x is the denominator and v is the resultant.循环,直到在元组的 x 或 v 中找到重复项,其中 x 是分母,v 是结果。

number=30
tuple_list=[]
for i in np.arange(1,number):
    if number%i==0:
         other=int(number/i)
         if any([(x,v) for (x,v) in tuple_list if (i==x) or (i==v)])==True:
             break
         tuple_list.append((i,other))
    
 flattened = [item for sublist in tuple_list for item in sublist]              
 print(sorted(flattened))

output输出

 [1, 2, 3, 5, 6, 10, 15, 30]

I found a simple solution using cypari library in python.我在 python 中使用 cypari 库找到了一个简单的解决方案。 Here's a link !这是一个链接

import cypari
def get_divisors(n):
   divisors = cypari.pari('divisors({})'.format(n))
   return divisors
print(get_divisors(24))

output输出

[1, 2, 3, 4, 6, 8, 12, 24]

We can use the following lambda function,我们可以使用以下 lambda 函数,

factor = lambda x:[(ele,x/ele) for ele in range(1,x//2+1) if x%ele==0 ]

factor(10)因素(10)

output: [(1, 10.0), (2, 5.0), (5, 2.0)]输出:[(1, 10.0), (2, 5.0), (5, 2.0)]

This function returns all the factors of the given number in list.此函数返回列表中给定数字的所有因子。

While the question says Python (2.7), people may be interested in this simple solution using Numpy.虽然问题是 Python (2.7),但人们可能会对这个使用 Numpy 的简单解决方案感兴趣。

import numpy as np

t=np.arange(2,n,1)
t[n%t==0]

This will not return 1 nor the number itself n .这不会返回1也不会返回数字本身n So it will return an empty array if n is prime.因此,如果n是素数,它将返回一个空数组。

Considering the number is positive integer, you may use this approach:考虑到数字是正数 integer,您可以使用这种方法:

number = int(input("Enter a positive number to find factors: "))
factor = [num for num in range(1,number+1) if number % num == 0]
for fac in factor: print(f"{fac} is a factor of {number}")

I'm a little surprised I couldn't find a simple implementation for integer prime factorization in the form (p1 ** e1) * (p2 ** e2)... , so I decided to write my own.我有点惊讶我找不到 integer 形式的素数分解的简单实现(p1 ** e1) * (p2 ** e2)... ,所以我决定自己写一个。

from collections import defaultdict
from itertools import count

def factorize(n):
    factors = defaultdict(int)
    for i in count(2):
        while n % i == 0:
            factors[i] += 1
            n /= i

        if n == 1:
            return factors

This function returns a dictionary where the keys are the prime factors, and the values are the exponents.这个 function 返回一个字典,其中键是质数因子,值是指数。 So for example:例如:

>>> factorize(608)
defaultdict(<class 'int'>, {2: 5, 19: 1})
>>> factorize(1152)
defaultdict(<class 'int'>, {2: 7, 3: 2})
>>> factorize(1088)
defaultdict(<class 'int'>, {2: 6, 17: 1})

This is obviously not the most efficient implementation — for one it iterates over the whole set of natural numbers, instead of going straight for the primes — but it's good enough for relatively small values, and simple enough that it can easily understood.这显然不是最有效的实现——因为它迭代整个自然数集,而不是直接针对素数——但它对于相对较小的值来说已经足够好了,而且足够简单,易于理解。

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

I reckon this is the simplest way to do that:我认为这是最简单的方法:

    x = 23

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM