Calculate the divisors of a number in Python in a performatic way

4

The code I'm using is:

import time

def divisores(num):
    for i in range(1, int(num/2+1)):
        if num % i == 0: 
           yield i
    yield num

inicio = time.time()

d = divisores(47587950)
[print(i) for i in d]

print("Fim da execução: %s segundos" % round((time.time() - inicio),2))

The return: Fim da execução: 5.94 segundos . This code is slow.

Is there a more performative way to calculate the divisors of a number using Python?

    
asked by anonymous 25.03.2017 / 19:32

2 answers

4

Tip: Do not use list comprehensions to perform functions like print() , append() etc ... will create you a temporary list full of None values, and has performance implications if this is very large, you can test this by doing print(print('hey')) whose print outer will print the return of print inner (which is None ), REF .

As for performance there is not much to do and your implementation is largely well done:

Way 1:

def divisores(num):
    for i in range(1, num//2+1):
        if num % i == 0: 
            yield i
    yield num

num = 47587950
print(list(divisores(num)))

Way 2:

num = 47587950
print([i for i in range(1, num//2+1) if num%i==0])

As for performance, the first way can be a bit faster, and if you do not make it into the list it's almost instantaneous:

STATEMENT

In the above demo:
using way 1 we have a time of 1.7259 secs
using way 2 we take 1.9021 secs

Remember that your computer should run faster than in Ideone.

Using the Way 1 function, the most appropriate way to print one at a time would be:

...
num = 47587950
for d in divisores(num):
    print(d)
    
25.03.2017 / 19:48
1

Numpy was born for this:

import numpy as np
import time

def divisores(num):
    n = np.arange(1,num)
    d = num % n
    zeros = d == 0
    print (n[zeros])

inicio = time.time()
divisores(47587950)
print("Fim da execução: %s segundos" % round((time.time() - inicio),2))  

Output:

[       1        2        3        5        6        9       10       15
       18       25       30       45       50       75       90      150
      225      450   105751   211502   317253   528755   634506   951759
  1057510  1586265  1903518  2643775  3172530  4758795  5287550  7931325
  9517590 15862650 23793975]  
Fim da execução: 0.99 segundos

It took 0.99 seconds here.

    
26.03.2017 / 18:13