1
num = input ()
fact = 0
while fact != num:
     fact = fact + 1
     rem = num % fact
     if rem == 0:
          print fact
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
pumba
  • 13
  • 2
  • 2
    This is a duplicate of [What is the best way to get all the divisors of a number?](http://stackoverflow.com/questions/171765/what-is-the-best-way-to-get-all-the-divisors-of-a-number) – Sven Marnach Nov 11 '10 at 01:03
  • 1
    In general, integer factorization is thought to be a very hard problem. See the [wikipedia entry](https://secure.wikimedia.org/wikipedia/en/wiki/Integer_factorization) for more info and better algorithms. – President James K. Polk Nov 11 '10 at 01:03
  • 4
    Suggested title: "how can I break RSA encryption efficiently?". – Glenn Maynard Nov 11 '10 at 01:11
  • If you like an answer then please upvote, leaving a thanks comment is also nice but an upvote is a better way to say thanks :) – anijhaw Nov 11 '10 at 03:01
  • please select an answer. – robert Nov 11 '10 at 23:42

7 Answers7

3

You only need to go to the square root of the input number to get all the factors (not as far as half the number, as suggested elsewhere). For example, 24 has factors 1, 2, 3, 4, 6, 8, 12, 24. sqrt(24) is approx 4.9. Check 1 and also get 24, check 2 and also get 12, check 3 and also get 8, check 4 and also get 6. Since 5 > 4.9, no need to check it. (Yes, I know 24 isn't the best example as all whole numbers less than sqrt(24) are factors of 24.)

factors = set()
for i in xrange(math.floor(math.sqrt(x))+1):
    if x % i == 0:
        factors.add(i)
        factors.add(x/i)
print factors

There are some really complicated ways to do better for large numbers, but this should get you a decent runtime improvement. Depending on your application, caching could also save you a lot of time.

robert
  • 33,242
  • 8
  • 53
  • 74
2

Use for loops, for starters. Then, let Python increment for you, and get rid of the unnecessary rem variable. This code does exactly the same as your code, except in a "Pythonic" way.

num = input()
for x in xrange(1, num):
    if (num % x) == 0:
        print fact

xrange(x, y) returns a generator for all integers from x up to, but not including y.

Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
2

So that prints out all the factors of a number? The first obvious optimisation is that you could quit when fact*2 is greater than num. Anything greater than half of num can't be a factor. That's half the work thrown out instantly.

The second is that you'd be better searching for the prime factorisation and deriving all the possible factors from that. There are a bunch of really smart algorithms for that sort of thing.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • 2
    You only need to search up to sqrt(n), if you have no factors by then there won't be any > sqrt(n) either – John La Rooy Nov 11 '10 at 01:31
  • Oh, good spot. It hadn't dawned on me that if you find one factor, you also simultaneously find another; there may be factors greater than sqrt(n), but n/f for such a factor, f, must be less than sqrt(n) and so f will be a factor you've already found. – Tommy Nov 11 '10 at 01:44
2

Once you get halfway there (once fact>num/2), your not going to discover any new numbers as the numbers above num/2 can be discovered by calculating num/fact for each one (this can also be used to easily print each number with its pair).

The following code should cust the time down by a few seconds on every calculation and cut it in half where num is odd. Hopefully you can follow it, if not, ask. I'll add more if I think of something later.

def even(num):
    '''Even numbers can be divided by odd numbers, so test them all'''
    fact=0
    while fact<num/2:
         fact+=1
         rem=num % fact
         if rem == 0:
              print '%s and %s'%(fact,num/fact)
def odd(num):
    '''Odd numbers can't be divided by even numbers, so why try?'''
    fact=-1
    while fact<num/2:
         fact+=2
         rem=num % fact
         if rem == 0:
              print '%s and %s'%(fact,num/fact)
while True:
    num=input(':')
    if  str(num)[-1] in '13579':
        odd(num)
    else:
        even(num)
AJ00200
  • 16,327
  • 7
  • 23
  • 21
  • 2
    I thought this was supposed to be a speed competition -- `str(num)[-1] in '13579'` is a baroque and slow way of determining whether `num` is odd; fortunately you do it only once; use `num % 2` or `num & 1` instead. – John Machin Nov 11 '10 at 04:05
1

Research integer factorization methods.

Russell Borogove
  • 18,516
  • 4
  • 43
  • 50
1

Yes. Use a quantum computer

Shor's algorithm, named after mathematician Peter Shor, is a quantum algorithm (an algorithm which runs on a quantum computer) for integer factorization formulated in 1994. Informally it solves the following problem: Given an integer N, find its prime factors.

On a quantum computer, to factor an integer N, Shor's algorithm runs in polynomial time (the time taken is polynomial in log N, which is the size of the input). Specifically it takes time O((log N)3), demonstrating that the integer factorization problem can be efficiently solved on a quantum computer and is thus in the complexity class BQP. This is exponentially faster than the most efficient known classical factoring algorithm, the general number field sieve, which works in sub-exponential time — about O(e1.9 (log N)1/3 (log log N)2/3). The efficiency of Shor's algorithm is due to the efficiency of the quantum Fourier transform, and modular exponentiation by squarings.

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
1

Unfortunately in Python, the divmod operation is implemented as a built-in function. Despite hardware integer division often producing the quotient and the remainder simultaneously, no non-assembly language that I'm aware of has implemented a /% or //% basic operator.

So: the following is a better brute-force algorithm if you count machine operations. It gets all factors in O(sqrt(N)) time without having to calculate sqrt(N) -- look, Mum, no floating point!

# even number

fact = 0
while 1:
    fact += 1
    fact2, rem = divmod(num, fact)
    if not rem:
        yield fact
        yield fact2
    if fact >= fact2 - 1:
        # fact >= math.sqrt(num)
        break
John Machin
  • 81,303
  • 11
  • 141
  • 189