Kosmoz
Kosmoz

Reputation: 91

Integer factorization in python

I've seen on this website many way of doing integer factorizations in python, but didn't really understand them, so I tried to do it on my own way :

def factorisation(n):
fact = []
i = 2
while i<=n:     
    if n%i==0:      
        fact.append(i)
        n//= i
    else:
        i+=1
return fact

I think it is working, but I don't really know why the while loop from i to n ... From my lesson I learnt that we have to do if from 2 to sqrt(n). Did I misunderstand something ? Can I improve it ? Thanks :)

Upvotes: 6

Views: 25771

Answers (6)

Konchog
Konchog

Reputation: 2188

(This is mainly for the benefit of those like me who just want to get a prime factorisation, and not write one).

from sympy import factorint
factorint(216)
factorint(98316592849045095018623091009)
{2: 3, 3: 3}
{3: 2, 19: 3, 31: 2, 479: 2, 659: 4, 38299: 1}

The response a key of the primes used, with their value being the number of times they are used.

Upvotes: 0

Alea Kootz
Alea Kootz

Reputation: 919

You only need to go to floor(sqrt(n)) if you are looking for smallest factor (such as in a primality test). if you want all the factors then you should check from 0 to n/2.

In short:

primality:

from math import sqrt

n = int(input('Please input a number: '))
sn = int(sqrt(n))
for x in range(2,sn+1):
    if n%x == 0:
        print('Not prime. Divisible by: '+str(x))
print(str(n)+' is prime')

factorization:

n = int(input('Please input a number: '))
n2 = int(n/2)
fn = []
for x in range(2,n2+1):
    if n%x == 0:
        fn.append(x) #lower member of factor pair
        fn.append(n/x) #upper member of factor pair
print('N has the following factors: '+str(fn))

I hope this helps you understand.

Upvotes: -4

Xiaofeng Zhang
Xiaofeng Zhang

Reputation: 1

An example of using recursive call:

def factoring(x, print_eq=True):
    factors = []
    if x == 2:
        factors += [x]
    for i in range(2,x):
        if i*i > x:
            factors += [x]
            break
        if x%i == 0:
            factors += [i]
            factors += factoring(x//i, False)
            break
    # Factorization has been completed.
    # Print the result in pretty mode
    if print_eq:
        if x in factors:
            print(f'{x} = 1 * {x} is a prime')
        else:
            eq = ''
            nf = {i : factors.count(i) for i in factors}
            fs = list(sorted(nf))
            for i, f in enumerate(fs):
                if nf[f] > 1:
                    eq += f'{f}^{nf[f]}'
                else:
                    eq += f'{f}'
                if i < len(fs) - 1:
                    eq += ' * '
            print(f'{x} = {eq}\n')
    return factors

Some examples:

factoring(23756965471926357236576238546) gives

23756965471926357236576238546 = 2 * 3^2 * 479 * 11423 * 582677 * 413975744296733

[2, 3, 3, 479, 11423, 582677, 413975744296733]

factoring(1024) gives

1024 = 2^10

[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

factoring(137) gives

137 = 1 * 137 is a prime

[137]

Upvotes: -1

Charles kluepfel
Charles kluepfel

Reputation: 11

This function with driver

def factors(n):
  global tmp
  answ=[]
  tmp=(n)
  addends=[4,2,4,2,4,6,2,6]
  def divn(dvr):
     
    
    global tmp
    while tmp%(dvr)==0:
      answ.append(dvr)
      tmp=tmp//dvr
       
  divn(2)
  divn(3)
  divn(5)
  d=(7)
  while (d)*(d)<=tmp:
     
    for i in range(8):
      divn(d)
      d=d+(addends[i])
  if tmp>1:
    answ.append(tmp)    
  return answ    
     
print(factors(23756965471926357236576238546))  

found

[2, 3, 3, 479, 11423, 582677, 413975744296733]

in 4 seconds. It does so by skipping over multiples of 2, 3 and 5 after testing those three primes. After testing for those three, it needs test only 8 out of every 30 numbers, starting with 7, in a cycle of addends given in the list of addends to the previously tested number. This cuts down on the number of non-primes used as a test. (30 is 235, so this constitutes the cycle of multiples of these).

Each tried number is tried as many times as needed until the remaining number is no longer divisible by it.

It uses a function within a function to try the actual division.

Upvotes: 0

JavDomGom
JavDomGom

Reputation: 1165

You can use Pollard's rho integer factorization algorithm. It's quite efficient and fast compared to other algorithms that are much slower. For example:

Python 3:

from math import gcd

def factorization(n):

    factors = []

    def get_factor(n):
        x_fixed = 2
        cycle_size = 2
        x = 2
        factor = 1

        while factor == 1:
            for count in range(cycle_size):
                if factor > 1: break
                x = (x * x + 1) % n
                factor = gcd(x - x_fixed, n)

            cycle_size *= 2
            x_fixed = x

        return factor

    while n > 1:
        next = get_factor(n)
        factors.append(next)
        n //= next

    return factors

With small numbers it's very fast, in this case it has taken only 0.035 seconds.

print(factorization(823767))
~$ time python3 factorization.py
[3, 7, 39227]

real    0m0,035s
user    0m0,031s
sys     0m0,004s

If we use slightly larger numbers the calculation time increases, but it's still very fast, in this case just 0.038 seconds.

print(factorization(41612032092))
~$ time python3 factorization.py
[3, 4, 37, 1681, 127, 439]

real    0m0,038s
user    0m0,034s
sys     0m0,004s

And if we use very large numbers it takes a little more time, but it's still a very reasonable time considering that it's a huge number. In this case just 28.128 seconds.

print(factorization(23756965471926357236576238546))
~$ time python3 factorization.py
[3, 3, 2, 479, 11423, 582677, 413975744296733]

real    0m28,128s
user    0m28,120s
sys     0m0,008s

I hope it helps you. Greetings.

Upvotes: 10

interjay
interjay

Reputation: 110069

When an integer n is not divisible by any number up to sqrt(n), that is sufficient to indicate that n is prime. In that case you won't find any additional factors other than n itself.

So what you can do is to stop the loop at sqrt(n), and add the remaining value of n to the list of prime factors.

Upvotes: 8

Related Questions