代码之家  ›  专栏  ›  技术社区  ›  Andrea Ambu

求一个数的所有除数的最佳方法是什么?

  •  86
  • Andrea Ambu  · 技术社区  · 18 年前

    def divisorGenerator(n):
        for i in xrange(1,n/2+1):
            if n%i == 0: yield i
        yield n
    

    我想得到的结果与这个类似,但我想要一个更智能的算法(这个算法太慢和愚蠢了:-)

    我可以很快找到素因子及其多重性。 我有一个生成器,它以这种方式生成因子:

    (因数1,倍数1)
    (系数2,倍数2)
    (系数3,多重性3)
    等等

    i、 e.项目的产出

    for i in factorGenerator(100):
        print i
    

    (2, 2)
    (5, 2)
    

    我不知道这对我想做的事情有多大用处(我为其他问题编写了代码),无论如何,我希望有一个更聪明的方法来解决这个问题

    for i in divisorGen(100):
        print i
    

    输出此项:

    1
    2
    4
    5
    10
    20
    25
    50
    100
    

    更新: 非常感谢格雷格·休吉尔和他的“聪明方式”:

    更新2: this 邮递计算一个给定数的除数并不需要计算所有的除数。这是一个不同的问题,如果你认为不是,那么在维基百科上寻找“除数函数”。在发帖前阅读问题和答案,如果你不明白主题是什么,就不要添加无用的和已经给出的答案。

    14 回复  |  直到 9 年前
        1
  •  80
  •   vvvvv lexa-b    6 年前

    考虑到你的 factorGenerator 函数,这里是一个 divisorGen 这应该是可行的:

    def divisorGen(n):
        factors = list(factorGenerator(n))
        nfactors = len(factors)
        f = [0] * nfactors
        while True:
            yield reduce(lambda x, y: x*y, [factors[x][0]**f[x] for x in range(nfactors)], 1)
            i = 0
            while True:
                f[i] += 1
                if f[i] <= factors[i][1]:
                    break
                f[i] = 0
                i += 1
                if i >= nfactors:
                    return
    

    该算法的总体效率将完全取决于算法的效率 因数发电机

        2
  •  36
  •   Eugene Yarmash    10 年前

    为了扩展Shimi所说的内容,您应该只运行从1到n的平方根的循环。然后,要找到这对,请执行以下操作: n / i ,这将覆盖整个问题空间。

    Python代码:

    import math
    
    def divisorGenerator(n):
        large_divisors = []
        for i in xrange(1, int(math.sqrt(n) + 1)):
            if n % i == 0:
                yield i
                if i*i != n:
                    large_divisors.append(n / i)
        for divisor in reversed(large_divisors):
            yield divisor
    
    print list(divisorGenerator(100))
    

    [1, 2, 4, 5, 10, 20, 25, 50, 100]
    
        3
  •  23
  •   Martijn Pieters    7 年前

    我想你可以在 math.sqrt(n)

    我会给你举个例子,这样你就可以很容易地理解它。现在 sqrt(28) 是 5.29 ceil(5.29) 六岁。如果我停在6,那么我可以得到所有的除数。怎样

    首先查看代码,然后查看图像:

    import math
    def divisors(n):
        divs = [1]
        for i in xrange(2,int(math.sqrt(n))+1):
            if n%i == 0:
                divs.extend([i,n/i])
        divs.extend([n])
        return list(set(divs))
    

    假设我已经添加了 1 i=2

    Divisors of a 28

    资料来源: How to determine the divisors of a number

        4
  •  22
  •   Tomas Kulich    7 年前

    虽然已经有很多解决方案,但我真的必须发布以下内容:)

    这个是:

    • 短的
    • 快速(在有大量素因子和除数的情况下,>比可接受的解决方案快10倍)
    • python3、python2和pypypy兼容

    def divisors(n):
        # get factors and their counts
        factors = {}
        nn = n
        i = 2
        while i*i <= nn:
            while nn % i == 0:
                factors[i] = factors.get(i, 0) + 1
                nn //= i
            i += 1
        if nn > 1:
            factors[nn] = factors.get(nn, 0) + 1
    
        primes = list(factors.keys())
    
        # generates factors from primes[k:] subset
        def generate(k):
            if k == len(primes):
                yield 1
            else:
                rest = generate(k+1)
                prime = primes[k]
                for factor in rest:
                    prime_to_i = 1
                    # prime_to_i iterates prime**i values, i being all possible exponents
                    for _ in range(factors[prime] + 1):
                        yield factor * prime_to_i
                        prime_to_i *= prime
    
        # in python3, `yield from generate(0)` would also work
        for factor in generate(0):
            yield factor
    
        5
  •  8
  •   Pietro Speroni    17 年前

    我喜欢Greg解决方案,但我希望它更像python。 所以经过一段时间的编码,我得出了这个结论。

    前两个函数用于生成列表的笛卡尔乘积。 顺便说一下,我必须自己编程,如果有人知道这个问题的标准解决方案,请随时与我联系。

    “Factorgenerator”现在返回一个字典。然后字典被输入到“除数”中,除数首先使用它生成一个列表列表,其中每个列表都是p^n形式的带p素数的因子列表。 然后我们对这些列表进行笛卡尔积,最后使用格雷格解生成除数。 我们将它们分类,然后返回。

    我测试了它,它似乎比以前的版本快了一点。我把它作为一个更大的程序的一部分进行了测试,所以我不能说它快了多少。

    from math import sqrt
    
    
    ##############################################################
    ### cartesian product of lists ##################################
    ##############################################################
    
    def appendEs2Sequences(sequences,es):
        result=[]
        if not sequences:
            for e in es:
                result.append([e])
        else:
            for e in es:
                result+=[seq+[e] for seq in sequences]
        return result
    
    
    def cartesianproduct(lists):
        """
        given a list of lists,
        returns all the possible combinations taking one element from each list
        The list does not have to be of equal length
        """
        return reduce(appendEs2Sequences,lists,[])
    
    ##############################################################
    ### prime factors of a natural ##################################
    ##############################################################
    
    def primefactors(n):
        '''lists prime factors, from greatest to smallest'''  
        i = 2
        while i<=sqrt(n):
            if n%i==0:
                l = primefactors(n/i)
                l.append(i)
                return l
            i+=1
        return [n]      # n is prime
    
    
    ##############################################################
    ### factorization of a natural ##################################
    ##############################################################
    
    def factorGenerator(n):
        p = primefactors(n)
        factors={}
        for p1 in p:
            try:
                factors[p1]+=1
            except KeyError:
                factors[p1]=1
        return factors
    
    def divisors(n):
        factors = factorGenerator(n)
        divisors=[]
        listexponents=[map(lambda x:k**x,range(0,factors[k]+1)) for k in factors.keys()]
        listfactors=cartesianproduct(listexponents)
        for f in listfactors:
            divisors.append(reduce(lambda x, y: x*y, f, 1))
        divisors.sort()
        return divisors
    
    
    
    print divisors(60668796879)
    

    附笔。 这是我第一次向stackoverflow发帖。

        6
  •  7
  •   ppw0    5 年前

    一个说明性的蟒蛇式单衬里:

    from itertools import chain
    from math import sqrt
    
    def divisors(n):
        return chain.from_iterable((i,n//i) for i in range(1,int(sqrt(n))+1) if n%i == 0)
    

    from sympy import divisors
    
        7
  •  5
  •   Bruno Astrolino    9 年前

    在纯Python 3.6中,这里有一种智能而快速的方法来处理10**16以内的数字,

    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))
    
        8
  •  2
  •   Community Mohan Dere    9 年前

    CodeReview ,这是一个与 num=1 !

    from itertools import product
    import operator
    
    def prod(ls):
       return reduce(operator.mul, ls, 1)
    
    def powered(factors, powers):
       return prod(f**p for (f,p) in zip(factors, powers))
    
    
    def divisors(num) :
    
       pf = dict(prime_factors(num))
       primes = pf.keys()
       #For each prime, possible exponents
       exponents = [range(i+1) for i in pf.values()]
       return (powered(primes,es) for es in product(*exponents))
    
        9
  •  1
  •   joksnet    10 年前

    老问题,但我的看法是:

    def divs(n, m):
        if m == 1: return [1]
        if n % m == 0: return [m] + divs(n, m - 1)
        return divs(n, m - 1)
    

    您可以通过以下方式代理:

    def divisorGenerator(n):
        for x in reversed(divs(n, n)):
            yield x
    

    注意:对于支持的语言,这可能是尾部递归的。

        10
  •  1
  •   Mathieu Villion    6 年前

    N = 10000000; tst = np.arange(1, N); tst[np.mod(N, tst) == 0]
    Out: 
    array([      1,       2,       4,       5,       8,      10,      16,
                20,      25,      32,      40,      50,      64,      80,
               100,     125,     128,     160,     200,     250,     320,
               400,     500,     625,     640,     800,    1000,    1250,
              1600,    2000,    2500,    3125,    3200,    4000,    5000,
              6250,    8000,   10000,   12500,   15625,   16000,   20000,
             25000,   31250,   40000,   50000,   62500,   78125,   80000,
            100000,  125000,  156250,  200000,  250000,  312500,  400000,
            500000,  625000, 1000000, 1250000, 2000000, 2500000, 5000000])
    

    在我速度较慢的电脑上只需不到1秒。

        11
  •  0
  •   user448810    13 年前

    factors 函数返回 N factors(60) 返回列表[2,2,3,5]),下面是一个计算 N :

    function divisors(n)
        divs := [1]
        for fact in factors(n)
            temp := []
            for div in divs
                if fact * div not in divs
                    append fact * div to temp
            divs := divs + temp
        return divs
    
        12
  •  0
  •   Amber Xue    11 年前

    这是我的解决办法。这看起来很傻,但效果很好…我试图找到所有合适的除数,所以循环从I=2开始。

    import math as m 
    
    def findfac(n):
        faclist = [1]
        for i in range(2, int(m.sqrt(n) + 2)):
            if n%i == 0:
                if i not in faclist:
                    faclist.append(i)
                    if n/i not in faclist:
                        faclist.append(n/i)
        return facts
    
        13
  •  0
  •   Sadiq    8 年前

    如果你只关心使用列表的理解,其他什么对你来说都不重要!

    from itertools import combinations
    from functools import reduce
    
    def get_devisors(n):
        f = [f for f,e in list(factorGenerator(n)) for i in range(e)]
        fc = [x for l in range(len(f)+1) for x in combinations(f, l)]
        devisors = [1 if c==() else reduce((lambda x, y: x * y), c) for c in set(fc)]
        return sorted(devisors)
    
        14
  •  0
  •   Arvind Pant    5 年前

    尝试计算给定数字的平方根,然后循环范围(1,平方根+1)。

    number = int(input("Enter a Number: "))
    square_root = round(number ** (1.0 / 2))
    print(square_root)
    divisor_list = []
    for i in range(1,square_root+1):
        if number % i == 0: # Check if mod return 0 if yes then append i and number/i in the list
            divisor_list.append(i)
            divisor_list.append(int(number/i))
    
    print(divisor_list)
    
        15
  •  0
  •   4b0 Agit    5 年前
    def divisorGen(n): v = n last = [] for i in range(1, v+1) : if n % i == 0 : last.append(i)
    
        16
  •  -1
  •   Veedrac    12 年前
    return [x for x in range(n+1) if n/x==int(n/x)]
    
        17
  •  -1
  •   tomekch6    12 年前

    对我来说,这很好,也很干净(Python 3)

    def divisors(number):
        n = 1
        while(n<number):
            if(number%n==0):
                print(n)
            else:
                pass
            n += 1
        print(number)
    

        18
  •  -1
  •   Eugene    6 年前

    def divisor(num):
        for x in range(1, num + 1):
            if num % x == 0:
                yield x
        while True:
            yield None