What would be the most optimal algorithm (performance-wise) to calculate the number of divisors of a given number?

It'll be great if you could provide pseudocode or a link to some example.

EDIT: All the answers have been very helpful, thank you. I'm implementing the Sieve of Atkin and then I'm going to use something similar to what Jonathan Leffler indicated. The link posted by Justin Bozonier has further information on what I wanted.

Given your reqs coming up with the number of factors is vague. I'm guessing you are looking for the number of non-unique prime divisors because if you didn't want that I code just write a program to always return 1 if the number to factor is one and 2 if it's anything else. 0 might need a change...
–
Justin BozonierSep 21 '08 at 6:09

@sker: Is there a range of Values for which you need the divisors. There are many ways of calculating the factors, and each method is better suited to a particular range.
–
AndeOct 30 '08 at 10:53

The naive Sieve of Atkin even from the edited Wikipedia article will never be faster than a maximally wheel factorized Sieve of Eratosthenes up to huge impractical limits, and the page segmented versions are even in more favour of the SoE (see SoE primesieve versus SoA primegen as implemented by Atkin's partner Bernstein. It is common incorrect Internet knowledge that the their study proved SoA faster, but they artificially limited the optimization of the SoE used in order to prove this. See my SoA answer for further explanation
–
GordonBGoodApr 3 at 4:52

22 Answers
22

Dmitriy is right that you'll want the Sieve of Atkin to generate the prime list but I don't believe that takes care of the whole issue. Now that you have a list of primes you'll need to see how many of those primes act as a divisor (and how often).

Essentially it boils down to if your number n is:n = a^x * b^y * c^z
(where a, b, and c are n's prime divisors and x, y, and z are the number of times that divisor is repeated)
then the total count for all of the divisors is:(x + 1) * (y + 1) * (z + 1).

Edit: BTW, to find a,b,c,etc you'll want to do what amounts to a greedy algo if I'm understanding this correctly. Start with your largest prime divisor and multiply it by itself until a further multiplication would exceed the number n. Then move to the next lowest factor and times the previous prime ^ number of times it was multiplied by the current prime and keep multiplying by the prime until the next will exceed n... etc. Keep track of the number of times you multiply the divisors together and apply those numbers into the formula above.

Not 100% sure about my algo description but if that isn't it it's something similar .

If you're factoring a large number, you don't even want to have to look at the prime list. You want to eliminate whole ranges of possibilities as quickly as possible! See my answer for more.
–
user11318Sep 21 '08 at 9:33

I realize this was 2 years ago, but your python algo link is broken, happen to know where it exists now?
–
jb.Apr 1 '11 at 6:19

There are a lot more techniques to factoring than the sieve of Atkin. For example suppose we want to factor 5893. Well its sqrt is 76.76... Now we'll try to write 5893 as a product of squares. Well (77*77 - 5893) = 36 which is 6 squared, so 5893 = 77*77 - 6*6 = (77 + 6)(77-6) = 83*71. If that hadn't worked we'd have looked at whether 78*78 - 5893 was a perfect square. And so on. With this technique you can quickly test for factors near the square root of n much faster than by testing individual primes. If you combine this technique for ruling out large primes with a sieve, you will have a much better factoring method than with the sieve alone.

And this is just one of a large number of techniques that have been developed. This is a fairly simple one. It would take you a long time to learn, say, enough number theory to understand the factoring techniques based on elliptic curves. (I know they exist. I don't understand them.)

Therefore unless you are dealing with small integers, I wouldn't try to solve that problem myself. Instead I'd try to find a way to use something like the PARI library that already has a highly efficient solution implemented. With that I can factor a random 40 digit number like 124321342332143213122323434312213424231341 in about .05 seconds. (Its factorization, in case you wondered, is 29*439*1321*157907*284749*33843676813*4857795469949. I am quite confident that it didn't figure this out using the sieve of Atkin...)

You're technique is very clever, but it doesn't tell me how many factors does the number have, does it?
–
skerSep 21 '08 at 18:09

17

Once you have the prime factorization, figuring out how many factors there are is straightforward. Suppose the prime factors are p1, p2, ..., pk and they are repeated m1, m2, ..., mk times. Then there are (1+m1)(1+m2)...(1+mk) factors.
–
user11318Sep 21 '08 at 20:59

An interesting sieve is the quadratic sieve. This uses number theory - quadratic congruences, and some linear algebra. I learned enough to use it in a 2nd year number theory course at university.
–
TannerNov 24 '12 at 4:28

This interesting question is much harder than it looks, and it has not been answered. The question can be factored into 2 very different questions.

1 given N, find the list L of N's prime factors

2 given L, calculate number of unique combinations

All answers I see so far refer to #1 and fail to mention it is not tractable for enormous numbers. For moderately sized N, even 64-bit numbers, it is easy; for enormous N, the factoring problem can take "forever". Public key encryption depends on this.

Question #2 needs more discussion. If L contains only unique numbers, it is a simple calculation using the combination formula for choosing k objects from n items. Actually, you need to sum the results from applying the formula while varying k from 1 to sizeof(L). However, L will usually contain multiple occurrences of multiple primes. For example, L = {2,2,2,3,3,5} is the factorization of N = 360. Now this problem is quite difficult!

Restating #2, given collection C containing k items, such that item a has a' duplicates, and item b has b' duplicates, etc. how many unique combinations of 1 to k-1 items are there? For example, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} must each occur once and only once if L = {2,2,2,3,3,5}. Each such unique sub-collection is a unique divisor of N by multiplying the items in the sub-collection.

Question #2 has a well known solution. For a factorization of { p_i, k_i } where p_i is a prime factor of a number with k_i multiplicity, the total number of divisors of that number is (k_1+1)*(k_2+1)*...*(k_n+1). I guess you know this by now but I write this down for the benefit if a random reader here.
–
Will NessSep 6 '12 at 16:20

An answer to your question depends greatly on the size of the integer. Methods for small numbers, e.g. less then 100 bit, and for numbers ~1000 bit (such as used in cryptography) are completely different.

JUST one line
I have thought very carefuly about your question and I have tried to write a highly efficient and performant piece of code
To print all divisors of a given number on screen we need just one line of code!
(use option -std=c99 while compiling via gcc)

for(int i=1,n=9;((!(n%i)) && printf("%d is a divisor of %d\n",i,n)) || i<=(n/2);i++);//n is your number

for finding numbers of divisors you can use the following very very fast function(work correctly for all integer number except 1 and 2)

NOTE:two above functions works correctly for all positive integer number except number 1 and 2
so it is functional for all numbers that are greater than 2
but if you Need to cover 1 and 2 , you can use one of the following functions( a little slower)

but why do you always increase the count by 2?...is there a theorem you applied?
–
SummerCodeMay 11 at 8:53

1

because you are conting only until sqrt(n). For eg: if you are trying to find all divisors for 36 - you will count from 2 to 6. You know that 1&36,2&18, 3&12, 4&9, 6,6 are all divisors and they come in pairs.
–
Antony ThomasMay 11 at 21:31

1

thanks a lot Anthony, i understood now :D! a small addendum: i think it should treat the sqrt(n) value separately because for now it takes it into consideration two times instead of one, i think
–
SummerCodeMay 12 at 7:23

It may be a quick leap, but testing all primes < sqrt(N) is still a bad factoring technique no matter how efficiently you find them. There are a lot of ways to improve that.
–
user11318Sep 21 '08 at 8:49

Testing the primes is O(N), it's finding the primes that's the hard part. But with even with the unoptimised sieve of eratosthenes, you can still find all primes under a few million in under a second. That covers any 64b number, and I'm sure we're not talking about factoring crypto level stuff here
–
Matthew ScharleyOct 6 '08 at 8:00

Divisors do something spectacular: they divide completely. If you want to check the number of divisors for a number, n, it clearly is redundant to span the whole spectrum, 1...n. I have not done any in-depth research for this but I solved Project Euler's problem 12 on Triangular Numbers. My solution for the greater then 500 divisors test ran for 309504 microseconds (~0.3s). I wrote this divisor function for the solution.

To every algorithm, there is a weak point. I thought this was weak against prime numbers. But since triangular numbers are not print, it served its purpose flawlessly. From my profiling, I think it did pretty well.

the prime number method is very clear here .
P[] is a list of prime number less than or equal the sq = sqrt(n) ;

for (int i = 0 ; i < size && P[i]<=sq ; i++){
nd = 1;
while(n%P[i]==0){
n/=P[i];
nd++;
}
count*=nd;
if (n==1)break;
}
if (n!=1)count*=2;//the confusing line :D :P .
i will lift the understanding for the reader .
i now look forward to a method more optimized .

Number theory textbooks call the divisor-counting function tau. The first interesting fact is that it's multiplicative, ie. τ(ab) = τ(a)τ(b) , when a and b have no common factor. (Proof: each pair of divisors of a and b gives a distinct divisor of ab).

Now note that for p a prime, τ(p**k) = k+1 (the powers of p). Thus you can easily compute τ(n) from its factorisation.

However factorising large numbers can be slow (the security of RSA crytopraphy depends on the product of two large primes being hard to factorise). That suggests this optimised algorithm

I'm confused. Counting all the primes less than the square root of a number will not give you it's divisors... not every prime less than the square root of a number will be a divisor for that number.
–
Garrett BergAug 2 '11 at 18:09