tags:

views:

154

answers:

5

What could be the simplest and time efficient logic to find out the factors of a given Number. Is there any algorithm that exist, based on the same.

Actually, my real problem is to find out the no. of factors that exist for a given Number..

So Any algorithm, please let me know on this..

Thanks.

+1  A: 

You may take a look at this algorithm.

Darin Dimitrov
+4  A: 

There is a large number of algorithms available - from simple trial devision to very sophisticated algorithms for large numbers. Have a look at Integer Factorization on Wikipedia and pick one that suits your needs.

Here is a short but inefficient C# implementation that finds the number of prime factors. If you need the number of factors (not prime factors) you have to store the prime factors with their multiplicity and calculate the number of factors afterwards.

var number = 3 * 3 * 5 * 7 * 11 * 11;

var numberFactors = 0;
var currentFactor = 2;

while (number > 1)
{
    if (number % currentFactor == 0)
    {
        number /= currentFactor;
        numberFactors++;
    }
    else
    {
        currentFactor++;
    }
}
Daniel Brückner
This is wrong. What are you even counting, factors or prime factors? This will give you 3 factors for 18, which is wrong either way.
IVlad
numberFactors counts the prime factors but my answer states that the number of factors can be derived from the prime factors and their multiplicity.
Daniel Brückner
You are wrong in saying that your solution counts the prime factors! `numberFactors` will contain the value `3` for `18`, which is wrong, there are only `2` prime factors in `18`: `2 and 3`.
IVlad
18 has three prime factors - two and twice three - but only two distinct prime factors.
Daniel Brückner
A: 

Euclid's Algorithm should suffice.

Jeremy Petzold
-1 Euclid's Algorithm does not find a factorization of an integer.
Daniel Brückner
Yes it does. it is a division algorithm which by definition will result in factors. Perhaps he should have specified PRIME factorization.
Jeremy Petzold
+2  A: 

Actually, my real problem is to find out the no. of factors that exist for a given Number..

Well, this is different. Let n be the given number.

If n = p1^e1 * p2^e2 * ... * pk^ek, where each p is a prime number, then the number of factors of n is (e1 + 1)*(e2 + 1)* ... *(ek + 1). More on this here.

Therefore, it is enough to find the powers at which each prime factor appears. For example:

read given number in n
initial_n = n
num_factors = 1;
for (i = 2; i * i <= initial_n; ++i) // for each number i up until the square root of the given number
{
    power = 0; // suppose the power i appears at is 0
    while (n % i == 0) // while we can divide n by i
    {
        n = n / i // divide it, thus ensuring we'll only check prime factors
        ++power // increase the power i appears at
    }
    num_factors = num_factors * (power + 1) // apply the formula
}

if (n > 1) // will happen for example for 14 = 2 * 7
{
    num_factors = num_factors * 2 // n is prime, and its power can only be 1, so multiply the number of factors by 2
}

For example, take 18. 18 = 2^1 * 3*2 => number of factors = (1 + 1)*(2 + 1) = 6. Indeed, the 6 factors of 18 are 1, 2, 3, 6, 9, 18.

Here's a little benchmark between my method and the method described and posted by @Maciej. His has the advantage of being easier to implement, while mine has the advantage of being faster if change to only iterate over the prime numbers, as I have done for this test:

 class Program
{
    static private List<int> primes = new List<int>();

    private static void Sieve()
    {
        bool[] ok = new bool[2000];

        for (int i = 2; i < 2000; ++i) // primes up to 2000 (only need up to sqrt of 1 000 000 actually)
        {
            if (!ok[i])
            {
                primes.Add(i);

                for (int j = i; j < 2000; j += i)
                    ok[j] = true;
            }
        }
    }

    private static int IVlad(int n)
    {
        int initial_n = n;
        int factors = 1;

        for (int i = 0; primes[i] * primes[i] <= n; ++i)
        {
            int power = 0;
            while (initial_n % primes[i] == 0)
            {
                initial_n /= primes[i];
                ++power;
            }
            factors *= power + 1;
        }

        if (initial_n > 1)
        {
            factors *= 2;
        }

        return factors;
    }

    private static int Maciej(int n)
    {
        int factors = 1;
        int i = 2;
        for (; i * i < n; ++i)
        {
            if (n % i == 0)
            {
                ++factors;
            }
        }

        factors *= 2;

        if (i * i == n)
        {
            ++factors;
        }

        return factors;
    }

    static void Main()
    {
        Sieve();


        Console.WriteLine("Testing equivalence...");

        for (int i = 2; i < 1000000; ++i)
        {
            if (Maciej(i) != IVlad(i))
            {
                Console.WriteLine("Failed!");
                Environment.Exit(1);
            }
        }

        Console.WriteLine("Equivalence confirmed!");

        Console.WriteLine("Timing IVlad...");
        Stopwatch t = new Stopwatch();

        t.Start();
        for (int i = 2; i < 1000000; ++i)
        {
            IVlad(i);
        }

        Console.WriteLine("Total milliseconds: {0}", t.ElapsedMilliseconds);
        Console.WriteLine("Timing Maciej...");

        t.Reset();
        t.Start();
        for (int i = 2; i < 1000000; ++i)
        {
            Maciej(i);
        }


        Console.WriteLine("Total milliseconds: {0}", t.ElapsedMilliseconds);
    }
}

Results on my machine:

Testing equivalence...
Equivalence confirmed!
Timing IVlad...
Total milliseconds: 2448
Timing Maciej...
Total milliseconds: 3951
Press any key to continue . . .

IVlad
Yeah the key is to realize that every divisor has it's counterpart and it's enough to loop up until the square root. However if one is looping from 2 to the square root anyway, checking for every i if it divides n, calculating powers and dividing n is waste of time in my opinion. Better to just increment the counter of factors.
Maciej Hehl
True, if `i` is a factor of `n` then so is `n / i`. That's another way of doing it that also allows going only up to the square root, just make sure that `i` and `n / i` are different so you don't count something twice! However, this doesn't allow you to only check primes, so I don't think it's always faster (with my posted method you can precompute the primes to make it faster). For example, for `20`, you must check `4` to realise that `4` and `5` are factors in the method you describe (if I'm thinking of the same thing).
IVlad
A: 

Here is a fruit of my short discussion with |\/|ad :)

read given number in n
int divisorsCount = 1;
int i;
for(i = 2; i * i < n; ++i)
{
    if(n % i == 0)
    {
        ++divisorsCount;
    }
}
divisorsCount *= 2;
if(i * i == n)
{
    ++divisorsCount;
}
Maciej Hehl
Yes, but you are iterating over EVERY number until the sqrt of `n`. My method has the potential of iterating only over the primes. This is easier to implement, but probably only preferable if you don't have to run it a lot of times.
IVlad