[Tutor] Prime Factorization Tool

Steven D'Aprano steve at pearwood.info
Fri Dec 2 00:56:12 CET 2011


Robert Sjoblom wrote:

> from math import sqrt
> 
> def isprime(n, factor):
>     if n == 1:
>         return False
>     for x in range(2, round(sqrt(n))):
>         if n % x == 0:
>             return False
>     else:
>         return True

factor is not used in the isprime function; get rid of it.

A bug in your code: the stop value in the call to range is sometimes off by 
one. That means that you sometimes wrongly pick a composite number as prime. 
E.g. isprime(25) returns True, but 25 is 5*5 and therefore not prime.

Remember that the "stop" value of the range function is not included in the range:

range(2, 5) => [2, 3, 4]

and so 5 is not tested. You need to include the sqrt. So you need to add 1 to 
the stop to ensure the sqrt is included:

range(2, round(sqrt(n))+1)

But this leads to a trivial inefficiency: sometimes you test one extra number. 
There's no need to round the square root up to the nearest value, e.g. square 
root of 115 is 10.723805294763608 which rounds up to 11. But there's no point 
in testing 11, since 11*11 = 121 > 115 and so 11 can't be a factor (assuming 
you have been reducing the number each time you find a smaller factor). 
Instead of using round, just use int(sqrt(n)) to drop the fractional part.

range(2, int(sqrt(n))+1)

A much more important inefficiency: you don't need to test by even numbers 
except for 2. If a number is divisible by 4, then it is also divisible by 2, 
and so even numbers will always be detected by the "divide by 2" step. Testing 
by dividing by 4, 6, 8, ... is pointless.

So you can roughly double the speed of your function by skipping even numbers 
other than two. Remember that 2 itself is prime, but any other multiple of 2 
is not. Take that test outside of the loop, and then loop over every second 
number starting with 3.

Hint: the range function takes a step size:

range(3, 25, 7) => [3, 10, 17, 24]


-- 
Steven



More information about the Tutor mailing list