0

I'm working on Project Euler, problem 3. The problem is:

"The prime factors of 13195 are 5, 7, 13 and 29. What is the largest prime factor of the number 600851475143?"

In answering this question, I'm breaking down the task to first find all prime numbers < x (in reverse). Why does the following code not seem to work, I'm not sure if it is the logic or incorrect use of operator.

#A function to find prime numbers under n
def find_prime(n):
    for i in reversed(xrange(2, n)):
        if (n % i) != 0:
            print i

find_prime(n)

In testing, I also built a prime number checker for fun, so I have tested somewhat.

def prime_checker(n):   
  if n > 2:
    for i in range (2,n):
      if (n % i) == 0:
        print "%s is not a prime number" % (n) 
        break
      else:
        print "%s is a prime number" % (n)

Can anyone help me understand what I'm doing wrong with the find_prime() function before I move on to the next step that I will use to solve the problem?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
mutantChickenHer0
  • 223
  • 1
  • 4
  • 14
  • 2
    You're reporting that a number is prime just because it's not divisible by one number. But it has to be not divisible by **any** number. – Barmar Apr 14 '16 at 21:15
  • Oops - I am saying "if n is not divisable by i, print i" – mutantChickenHer0 Apr 14 '16 at 21:20
  • You don't want to find all the primes smaller than N. Most of thm will not be a factor of N. You want to find 'the next' prime factor after the last one you checked (start with 2, 3, 5, 7, …). When you find one that's a factor of N (say P), you then work with N1 = N / P to find further factors, reducing the range to be searched. Your sample number has factors 71, 839, 1471, 6857. There are more than 50 million primes smaller than 1E9, so your number will have many more factors smaller than it. But finding just the 882 primes up to 6857 will be sufficient. – Jonathan Leffler Apr 14 '16 at 21:48
  • Having said that, you might need to allow for it being the product of a small prime and a very large prime. You should look up the [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes); at least you then can then stop after you reach √600851475143 or 775146. – Jonathan Leffler Apr 14 '16 at 21:48
  • @JonathanLeffler just 233 primes *<= 1471* is enough here (*sqrt (6857)* is *82*). or the 735 odds. – Will Ness Apr 15 '16 at 14:29
  • @WillNess: oh, right…but it only makes my "you don't need all primes up to the 12-digit number" point even stronger. – Jonathan Leffler Apr 15 '16 at 14:42

2 Answers2

3

Before you start coding, maybe you should read up a bit on what you are dealing with. Primes are well studied. First of all, you do not need all the primes < x. Secondly, every time you find a divisor, you can divide the number by that and have a smaller problem on your hands. In the end, the number that will be left will be what you are looking for. Now, except for 2, no other even numbers are primes, so xrange(3, n, 2). Search some more and you'll find a solution that won't need the time of the universe to finish.

kameranis
  • 284
  • 1
  • 13
  • Ack. My intention here is to break the problem down before making it the best solution available. Your point makes sense to me. – mutantChickenHer0 Apr 14 '16 at 21:27
  • ok, how would you find a large sequence of consecutive primes? Do not check each one separately. Implement Aritosthene's Seeve. There is a good explanation about it on Wikipedia. – kameranis Apr 14 '16 at 22:19
  • @mutantChickenHer0 in divide and conquer, there's not only divide, but conquer too is important. here, there's much synergy when those individual functions are combined, leading to many opportunities for removal of repeated calculations (like, there's no need to prove what's true by construction, etc.). e.g. see [this answer](http://stackoverflow.com/a/24169277/849891), or wade through [these](https://stackoverflow.com/search?q=%5Bpython%5D+600851475143+is%3Aa). – Will Ness Apr 15 '16 at 14:36
2

You can't tell whether a number is prime until you make it all the way through the loop without finding any divisors. You're reporting that a number is prime as soon as you find a number that doesn't divide it, but it might still be divisible by some higher number. Your code will say that all odd numbers are prime, because they aren't a multiple of 2.

Also, it's not necessary to go all the way to n in your range. None of the factors of a number can be greater than the square root of the number.

def prime_checker(n):   
  if n > 2:
    for i in range (2, int(n ** .5)+1):
      if (n % i) == 0:
        print "%s is not a prime number" % (n) 
        return false
  print "%s is a prime number" % (n)
  return true
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • "All the factors of a number must be less than the square root of the number." No. For example, 49 has the proper factor 7, which is also the square root. You always need to test up to *and including* the square root in case the number being tested is the square of a prime. – rossum Apr 15 '16 at 16:35
  • Thanks for the correction. I've updated the code to add 1 to the square root so the range will stop at the root. – Barmar Apr 15 '16 at 16:45