Prime number finder including 2 multiple times - python

This program makes a list of all prime numbers less than or equal to a given input.
Then it prints the list.
I can't understand why it includes the number 2. When I first designed the program, I initialized the list with primes = [2] because I thought, since 2 % 2 == 0,
if n % x == 0:
is_prime = False
will set is_prime to False. However, that doesn't seem to be the case.
I'm sure there is something going on with the logic of my range() in the for loops that I just don't understand.
I guess my question is: Why is 2 included in the list of primes every time?
import math
limit = int(input("Enter a positive integer greater than 1: "))
while limit < 2:
limit = int(input("Error. Please enter a positive integer greater than 1: "))
primes = []
#Check all numbers n <= limit for primeness
for n in range (2, limit + 1):
square_root = int(math.sqrt(n))
is_prime = True
for x in range(2, (square_root + 1)):
if n % x == 0:
is_prime = False
if is_prime:
primes.append(n)
#print all the primes
print("The primes less than or equal to", limit, "are:")
for num in primes:
print(num)

Because you don't enter the second for-loop when you test for n=2 and therefore you don't set is_prime = False.
# Simplified test case:
x = 2
for idx in range(2, int(math.sqrt(x))+1):
print(idx)
This doesn't print anything because range is in this case: range(2, 2) and therefore has zero-length.
Note that your approach is not really efficient because:
you test each number by all possible divisors even if you already found out it's not a prime.
you don't exclude multiples of primes in your tests: if 2 is a prime, every multiple of 2 can't be prime, etc.
There are really great functions for finding prime numbers mentioned in Fastest way to list all primes below N - so I won't go into that. But if you're interested in improvements you might want to take a look.

Related

Python code that creates list of prime numbers

Trying to create a list of prime numbers in a fixed range. This is producing non-sensical list but the code makes sense to me.
for number in range(2,100,2):
k = 1
while k*k < number:
k += 2
if number % k == 0:
break
else:
print(number)
there are several bugs in your code.
first, you don't check its divisibility by even numbers, any even number to be exact (including 2)! if it is meant as an optimization approach, make it more generic by not checking the numbers who are known already not to be prime. its called the sieve of eratosthenes
another, is that you don't check the divisibility if n is a square root of a prime number as you pass the k*k = number case.
this is my implementation for a naive n * sqrt(n):
for number in range(2,100):
prime, divisor = True, 2
while prime and divisor ** 2 <= number:
if number % divisor == 0:
prime = False
divisor += 1
if (prime):
print(number)
Change like this:
for number in range(2, 101):
for k in range(2, number):
if (number % k) == 0:
break
else:
print(number)
for number in range(1,100):
counter=0
for test in range(1,number+1):
if number%test==0:
counter=counter+1
if counter<=2:
print(number)

Calculating the thousandth prime

The problem asks to calculate the 1000th prime number. I am trying to solve this problem but I am stuck.
There are some guidelines on how to solve the problem.
To help you get started, here is a rough outline of the stages you should probably follow in
writing your code:
Initialize some state variables
Generate all (odd) integers > 1 as candidates to be prime
For each candidate integer, test whether it is prime
One easy way to do this is to test whether any other integer > 1 evenly
divides the candidate with 0 remainder. To do this, you can use modular
arithmetic, for example, the expression a%b returns the remainder after
dividing the integer a by the integer b.
You might think about which integers you need to check as divisors –
certainly you don’t need to go beyond the candidate you are checking, buthow much sooner can you stop checking?
If the candidate is prime, print out some information so you know where you are
in the computation, and update the state variables
Stop when you reach some appropriate end condition. In formulating this
condition, don’t forget that your program did not generate the first prime (2).
Use these ideas to guide the creation of your code.
My attempt so far is this
def calculate_thousandth_prime():
j = 0
for i in range(3,int(10e6)):
if i%2 != 0:
counter = 0
for k in range(1, i):
if i%k != 0:
counter += 1
if counter == 0:
print("This candidate is prime")
j += 1
if j == 1001:
print("The number "+str(i)+" is the thousandth prime")
break
return 0
calculate_thousandth_prime()
My code gets stuck on i%k != 0. I must be doing something wrong... any help?
You have two problems:
First, you're searching for k in range(1, i):. Because every number, including primes, is divisible by 1, you won't find any primes. Try searching range(2, i) instead.
Second, you're checking if i%k != 0:. You should be checking that i%k == 0 instead. If i is divisible by any number k, then the number is not prime.
Actually, I found a third issue: You have an off-by-one error. By initializing j=0, your code considers the first prime it finds to be the "zeroth" prime. The code will output the thousand-and-first prime, instead of the thousandth prime.
Changes I made:
Change your range to add a 2 step to skip even numbers more naturally.
Check your inner loop, you need to divide by the values range(2, i//2). Dividing by anything greater than i//2 will be less than 2.
Change your prime check to see if any number in the above range divides. If so, we know the number is false. At that point we can move onto the next number.
We want to return when the prime counter is 1000, you were returning the 1001th prime.
def calculate_thousandth_prime():
prime_counter = 0
for i in range(3,int(10e6),2):
prime = True
for k in range(2, i//2):
if i % k == 0:
prime = False
break
if prime:
print(str(i) + " is prime")
prime_counter += 1
if prime_counter == 1000:
print("The number "+str(i)+" is the thousandth prime")
break
return i
calculate_thousandth_prime()
The sieve of Eratosthenes is generally the fastest way for the early primes. You can adapt it to reach the nth prime.
For example:
def nthPrime(N):
sieve = [1]*(N**2)
p = 2
for _ in range(N):
while not sieve[p]: p += 1
sieve[p::p] = [0]*len(sieve[p::p])
return p
nthPrime(100) # 541
The prime list divisor check method is probably easier to write and understand but it is much slower (although for only 1000 primes, this wouldn't make much of a difference):
def nthPrime(N):
primes = [2]
p = 1
while len(primes)<N:
p += 2
primes += [p]*all(p%d for d in primes)
return p

Find prime numbers less than or equal to the number the user has entered with loops. How do I do that?

With this code, I only get to test if the number the user entered is prime or not.
How do I add another loop to my original code in order to find all the prime numbers less than or equal to the number the user has entered?
num = int(input("Enter a number: "))
if num > 1:
prime = True
for n in range(2, num):
if (num % n) == 0:
print ("Number", num, "is not prime")
break
else:
print("Number", num, "is prime")
You can'not print both in one loop, you can do one thing add a loop above your current loop and display each number like this :
num = int(input("Enter a number: "))
if num > 1:
prime = True
for n in range(2, num):
if (num % n) == 0:
print ("Number", num, "is not prime")
break
else:
print("Number", num, "is prime")
#your current code ends here
for j in range(2, num + 1):
# prime numbers are greater than 1
for i in range(2, j):
if (j % i) == 0:
break
else:
print(j)
Your code only check the number entered is prime or not , but you questioned about to get prime numbers from 2 to n (n = number entered by user) for this you run below code with the help of flag bit it will little bit easy for you. i hope it will help you.
Try This i run this code It will Surely help you to find your answer it work in python 3.0 or above
num = int(input("Enter The Number"))
if num > 1:
num = num+1
list = []
for j in range (2,num,1):
flag = 0
for i in range (2,int(j/2)+1,1):
if(j%i)== 0:
flag = 1
break
if flag==0:
list.append(j)
print(list)
else:
print("Enter Number Greater Than 1")
Aside from small things (unused boolean variable) your prime test is also super inefficient.
Let's go through this step by step.
First: To test if a number is prime, you don't need to check all integers up to the number for divisors. Actually, going up to sqrt(num) turns out to be sufficient. We can write a one-liner function to find out if a number is prime like so:
from numpy import sqrt
def is_prime(n):
return n > 1 and all(n%i for i in range(2,int(sqrt(n))+1))
range(2,some_num) gives an iterator through all numbers from 2 up to some_num-1and the all() function checks if the statement n%i is true everywhere in that iterator and returns a boolean. If you can guarantee to never pass even numbers you can start the range from 3 (of course with the loss of generality). Even if you don't want to use that function, it's cleaner to separate the functionality into a different function, because in a loop of numbers up to your input you will probably have to check each number for being prime separately anyways.
Second: From here, finding all primes smaller or equal than your input should be pretty easy.
num = int(input("Enter a number:"))
assert num>0, "Please provide a positive integer" # stops with an assertion error if num<=0
prime_lst = [2] if num > 1 else []
for x in range(3,num+1,2):
if is_prime(x):
prime_lst.append(x)
The list prime_lst will contain all your sought after prime numbers. I start the loop from 1 such that I can loop through only the odd numbers, even numbers are divisible by two. So this way none of the numbers will be divisible by two. Unfortunately this requires me to check if the number itself may be 2, which is a prime. By the twin-prime conjecture we can not simplify this range further without knowing about the input.
Finally: If you really want to find the primes in one loop, change your loop to something along the lines of:
prime_lst = [2] if num > 1 else []
for x in range(3,num+1,2): # outer loop
for i in range(3,int(sqrt(x))+1): # inner loop for check if x is prime
if x%i == 0:
break # breaks the inner loop, number is not prime
else:
prime_lst.append(x)
Edit: Just saw that the second answer here has a good explanation (and an even better way) of writing the one-liner for finding out if a number is prime.

Finding a prime number

The problem is that you need to find the prime number after the number input, or if the number input is prime, return that. It works fine. It's just not working when the input is print(brute_prime(1000)). It returns 1001 not 1009. The full code is this:
def brute_prime(n):
for i in range(2, int(n**(0.5))):
if n % i == 0:
n += 1
else:
return n
As Barmar suggests, you need to restart the loop each time you increment n. Your range also ends earlier than it should, as a range stops just before the second argument.
def brute_prime(n):
while True:
for i in range(2, int(n**(0.5)) + 1):
if n % i == 0:
break
else:
return n
n = n+1
remember 2 is a prime number. again you can just check the division by 2 and skip all the even number division
def brute_prime(n):
while True:
if n==2:return n
elif n%2 ==0 or any(n % i==0 for i in range(3, int(n**(0.5)+1),2)):
n += 1
else:
return n
You're not restarting the for i loop when you discover that a number is not prime and go to the next number. This has two problems: you don't check whether the next number is a multiple of any of the factors that you checked earlier, and you also don't increase the end of the range to int(n ** 0.5) with the new value of n.
def brute_prime(n):
while true:
prime = true
for i in range(2, int(n ** 0.5)+1):
if n % i == 0:
prime = false
break
if prime:
return n
n += 1
break will exit the for loop, and while true: will restart it after n has been incremented.
as mention by Chris Martin the wise solution is define a isPrime function separately and use it to get your desire number.
for example like this
def isPrime(n):
#put here your favorite primality test
from itertools import count
def nextPrime(n):
if isPrime(n):
return n
n += 1 if n%2==0 else 2
for x in count(n,2):
if isPrime(x):
return x
if the given number is not prime, with n += 1 if n%2==0 else 2 it move to the next odd number and with count check every odd number from that point forward.
for isPrime trial division is fine for small numbers, but if you want to use it with bigger numbers I recommend the Miller-Rabin test (deterministic version) or the Baille-PSW test. You can find a python implementation of both version of the Miller test here: http://rosettacode.org/wiki/Miller%E2%80%93Rabin_primality_test#Python

Prime factorization: doesn't work with large numbers?

I'm trying to find the largest prime factor for a number. The code runs correctly on IDLE when used with smaller numbers, but doesn't seem to print anything to the screen at all when I assign a larger number like 600851475143 to n. Why?
def isPrime(n):
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
I'm running Python 3.3, by the way.
==============================================================================
Thanks everyone!
I fixed my original code as follows:
def isPrime(n):
for i in range(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
if i == n:
break
n = n / i
print("The largest prime factor is", largest)
Like nakedfanatic said, their code runs faster, and I edited it slightly:
largest = 0
n = 600851475143
i = 2
while True:
if n % i == 0:
largest = i
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", largest)
There are several areas of optimization:
all factorization only needs to got up to sqrt(n) (inclusive)
convert isPrime() to a table lookup
Initialize a lookup table using n, then you compute all primes < sqrt(n) only once and loop through them.
As comments pointed out, this takes up large memory space. We can use bit flag to cut the memory requirement to 1/8, and we can cut it by a further half if we skip all the even numbers (then have to test if n is even separately). But that may still be daunting for LARGE n.
(if using current code) return early in isPrime() (by #justhalf)
loop backwards (from sqrt(n) to 2) when looking up the largest factor
return early if the quotient is 1 after dividing by a factor (by #justhalf)
This post (suggested by #prashant) contains more complicated algorithm (making my suggestion very naive ><):
Fastest way to list all primes below N
... (edits are welcome)
It's because you keep trying even if n is already 1.
This code will help you to see the problem:
def isPrime(n):
for i in xrange(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in xrange(2,n-1):
print 'Checking whether %d divides %d' % (i,n)
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
which will produce:
...
Checking whether 6857 divides 6857
Checking whether 6858 divides 1
Checking whether 6859 divides 1
Checking whether 6860 divides 1
Checking whether 6861 divides 1
Checking whether 6862 divides 1
Checking whether 6863 divides 1
Checking whether 6864 divides 1
Checking whether 6865 divides 1
Checking whether 6866 divides 1
Checking whether 6867 divides 1
Checking whether 6868 divides 1
Checking whether 6869 divides 1
Checking whether 6870 divides 1
Checking whether 6871 divides 1
Checking whether 6872 divides 1
Checking whether 6873 divides 1
...
You should break the loop when n becomes 1, so that it won't do unnecessary checking
n = n / i
if n==1:
break
continue
And anyway, your code might be improved by a lot, haha, see others' suggestions.
Most likely, your code isn't terminating with large n, simply because it takes so long to run through the loop.
Your code is running in O(n²) time, which means it will quickly become unreasonably slow as the size of n increases. That is why your algorithm works for small values, but hangs for large values.
This code does the same thing in O(n) time without doing any prime checking at all, and returns a result instantly:
prime_factors = []
n = 600851475143
i = 2
while True:
if n % i == 0:
prime_factors.append(i)
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", prime_factors[-1])
More difficult problems may require a different algorithm.
Check this question out: Fastest way to list all primes below N
Your code looks okay, but could take a long time for a large n. Leveraging math can enable you to do this problem orders of magnitude faster.
On that link, I recommend rwh_primes1 for a pure python solution, and primesfrom3to as one that uses numpy. Both of those implementations are fairly short, relatively clear, and do basically the same thing. Those code snippets are written in Python 2, so a translation might look like this:
def rwh_primes1(n):
sieve = [True] * (n//2)
for i in range(3, int(n**0.5)+1,2):
if sieve[i//2]:
sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
return [2] + [2*i+1 for i in range(1,n//2) if sieve[i]]
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
This loop always exits the first iteration due to the unconditional return. Try:
for i in range(2,n-1):
if n % i == 0:
return False
return True
Also the upper bound n-1 can be reduced to sqrt(n)+1.
Another aspect of your code which may be slowing it down is the second half of your code
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
Specifically the statement
if isPrime(i) and n % i == 0:
Per the documentation, the second condition is only evaluated if the first one is True. In your case it would make more sense to reverse the conditions so that computationally les expensive division is performed always and the more expensive isPrime() is only called for the actual factors
largest = 0
n = 600851475143
for i in range(2,n-1):
if n % i == 0 and isPrime(i):
largest = i
n = n / i
if n == 1:
break

Categories