pythonmath

The most optimized way to find the sum of divisors of a number for numbers in a given range in python


I would like to find the sum of divisors of a number for numbers in a given range in the fastest possible way.

My current one looks like this

import math


def divSum(num):
    result = 0

    for i in range(2, int(math.sqrt(num)+1)):
        if num % i == 0:
            if i == (num / i):
                result = result + i
            else:
                result = result + (i + num / i)
    return int(result + 1)


list_of_number = [*range(0, 1000000, 1)]

print(list(map(divSum, list_of_number)))

At 100,000, the problems begin. Is there any way to optimize or the current one is fine overall. Thank you


Solution

  • In your particular case I would say the fastest you can get is the Sieve of Eratosthenes. This way we avoid work duplication. Keep in mind that this approach is good as long as you need the result for all numbers between 0 and 1e6. This might not be the best idea to compute the sum for a particular number.

    # Set how many numbers we are testing
    MAX = 1_000_000
    # Initialize a list to avoid memory reallocation
    # Set 1 as initial value as all numbers are divisible by 1
    SUMS = [1] * (MAX + 1)
    # Take every number and add it to all its multiples not grater than MAX
    # No number not grater than MAX will have a divisor higher than MAX / 2
    for i in range(2, (MAX + 1) // 2):
        # Don't start at i to avoid adding i to its own sum
        for index in range(i * 2, MAX + 1, i):
            # i is a divisor of index
            SUMS[index] += i
    

    In my machine this code took 1.5 seconds.

    Once we have the list SUMS, we can get the result of your function in constant time. For all i from 0 to MAX, SUMS[i] returns the same as divSum(i).