for x in range (3,21):
if(x%2==0):
print (x,'is a not a prime number')
else:
print (x,'is a prime number')
This is my code but when it prints it says 9 is a prime number and 15 is a prime number.
Which is wrong because they aren't so how do I fix that?
.
def isPrime(N):
i = 2
while i**2 <= N:
if N % i == 0:
return False
i+=1
return True
for i in range(3, 21 + 1):
if isPrime(i):
print(i, 'is prime')
else:
print(i, 'is not a prime number')
First of all, create a function for determining whether or not a given number is prime (this is not a requirement but just a good practice). That function is not that hard: it just starts at i = 2 (starting at 1 makes no sense because every number can be divided by it) and check if N can be divided by it. If that is the case, we have found a divisor of N and thus, it isnt prime. Otherwise, continue with the next number: i += 1. The most tricky part of the loop is the stoping condition: i**2 <= N: we dont have to look further, because if some j > i is a divisor of N, then there is some other k < i that is also a divisor of N: k * j == N. If such k exists, we will find it before getting to the point where i * i == N. Thats all. After that, just iterate over each number you want to check for primality.
Btw, the best way to check for the primality of a set of number is using the Sieve of Eratosthenes
Your code only checks if a number is even. All odd numbers are not prime. So write a for-loop that checks if a odd number is divisible by any of the odd number less than that. Sometying like:
For i in (3 to n): If n mod i == 0, n is not prime.
Related
I am trying to solve Project Euler number 7.
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10 001st prime number?
First thing that came into my mind was using length of list. This was very ineffective solution as it took over a minute. This is the used code.
def ch7():
primes = []
x = 2
while len(primes) != 10001:
for i in range(2, x):
if x % i == 0:
break
else:
primes.append(x)
x += 1
print(primes[-1])
ch7()
# Output is: 104743.
This works well but I wanted to reach faster solution. Therefore I did a bit of research and found out that in order to know if a number is a prime, we need to test whether it is divisible by any number up to its square root e.g. in order to know if 100 is a prime we dont need to divide it by every number up to 100, but only up to 10.
When I implemented this finding weird thing happened. The algorithm included some non primes. To be exact 66 of them. This is the adjusted code:
import math
primes = []
def ch7():
x = 2
while len(primes) != 10001:
for i in range(2, math.ceil(math.sqrt(x))):
if x % i == 0:
break
else:
primes.append(x)
x += 1
print(primes[-1])
ch7()
# Output is 104009
This solution takes under a second but it includes some non primes. I used math.ceil() in order to get int instead of float but I figured it should not be a problem since it still tests by every int up to square root of x.
Thank you for any suggestions.
Your solution generates a list of primes, but doens't use that list for anything but extracting the last element. We can toss that list, and cut the time of the code in half by treating 2 as a special case, and only testing odd numbers:
def ch7(limit=10001): # assume limit is >= 1
prime = 2
number = 3
count = 1
while count < limit:
for divisor in range(3, int(number ** 0.5) + 1, 2):
if number % divisor == 0:
break
else: # no break
prime = number
count += 1
number += 2
return prime
print(ch7())
But if you're going to collect a list of primes, you can use that list to get even more speed out of the program (about 10% for the test limits in use) by using those primes as divisors instead of odd numbers:
def ch7(limit=10001): # assume limit is >= 1
primes = [2]
number = 3
while len(primes) < limit:
for prime in primes:
if prime * prime > number: # look no further
primes.append(number)
break
if number % prime == 0: # composite
break
else: # may never be needed but prime gaps can be arbitrarily large
primes.append(number)
number += 2
return primes[-1]
print(ch7())
BTW, your second solution, even with the + 1 fix you mention in the comments, comes up with one prime beyond the correct answer. This is due to the way your code (mis)handles the prime 2.
I am trying to calculate prime factors of a number in python python 3.8.2 32bit (when i pass 35 in code its output should be 7,and so on).But for some reason the program does not return any answer (when i click run the cmd does not output anything).But when i run this javascript, the exact same code works there. (Previously i had an array(list) to which i would append prime factors and at last i would pop the last element which worked for smaller numbers , but for really large numbers i would get a Memory error,so i converted it to use only one variable which will be updated for every while loop). What is going on here ??
My code is :
import math
# Computes only prime factors of n
def compute(n):
arr = 0
# Checks if n is divisible by 2, and if it is divisible,returns 2 because there will be no any other
# prime factor.
if n % 2 == 0:
return 2
# Now that 2 is eliminated we only check for odd numbers upto (square root of n)+1
for i in range(1, round(math.sqrt(n)) + 1, 2):
while n % i == 0:
arr = n/i
n /= i
return str(arr)
print(compute(81))
I am a newbie in python so plz tell me if i have made any silly mistakes.
Ty.
For numbers that are not divisible by 2, your code runs into an infinite loop at
while n%i == 0
For numbers that are divisible by 2, your function returns 2. The execution of the return statement exits the function.
Even if you change the while in while n%i == 0 to if n% == 0 the function will not work.
You will have to restructure your code.
An easy fix would be to check for all factors of a number till n/2 + 1 and return the factors (in a list) that are prime (which can be checked using a separate isprime function.
def isprime(n):
for x in range(2,n//2+1):
if n%x==0:
return False
return True
def compute(n):
arr = []
for i in range(2, n//2+1):
if n % i == 0:
if isprime(i):
arr.append(i)
return arr
If you want all prime factors (which i guess) you shouldn't return values before you have all prime factors in a list for example.
And with this programm you only check once for a 2. But 4 has 2*2. Put it in a loop.
So this code saves all prime factors in a list:
from math import sqrt, ceil
def get_prime_factors(n):
prime_factors = []
while n > 1:
for i in range (2, ceil(sqrt(n))+1):
if n % i == 0:
possible_prime_number = i
while True:
for j in range(2, possible_prime_number//2-1):
if possible_prime_number % j == 0:
possible_prime_number //= j
break
prime_factors.append(possible_prime_number)
n //= possible_prime_number
break
return prime_factors
if you only want the highest one replace return prime_factors with return max(prime_factors)
OK. I think counting upto 600 billion is ridiculous(considering that i am on a 32 bit system). So here is the final code that i am setteling on which gives answer in acceptable time upto 99 million, without using any array and only 1 for loop.
from math import ceil
# Computes only prime factors of n
def compute(n):
arr = 0
# Checks if n is divisible by 2, and if it is divisible,sets arr =2
if n % 2 == 0:
arr = 2
# Now that 2 is eliminated we only check for odd numbers upto (square root of n)+1
for i in range(1, ceil(n/2) + 1, 2):
if n % i == 0:
arr = i
n //= i
return str(arr)
print(compute(999999999))
P.S.:- If you see any possible improvement in my code plz tell me.
Given an integer n, the function legendre_n should return the number of prime numbers between n^2 and (n+1)^2.
This is the code I wrote:
def legendre_n(n):
"""Returns the number of primes between n**2 and (n+1)**2"""
count = 0
for i in range(n**2, ((n+1)**2)):
if i%2 != 0:
count += 1
return count
print(legendre_n(12)) = > 5 but I'm getting 12
print(legendre_n(3)) => 2 but I'm getting 4
After testing on python tutor, I found out that the condition I set (i%2 != 0) only filters out odd numbers. However, not all odd numbers are prime numbers. I understand that prime numbers should only be divisible by 1 and the number itself, but I'm stucked at setting the correct condition.
This should do the trick:
def legendre_n(n):
"""Returns the number of primes between n**2 and (n+1)**2"""
count = 0
for num in range(n**2, ((n+1)**2)):
if num > 1:
for i in range(2, num):
if (num % i) == 0:
break
else:
count = num
return count
you want to check either your num is devidable with any other number between 2 and itself (modulo calculation). If not, it is a prime number.
There is no known "fast" computation to determining if a number is prime. The only known methods involve loops of checks (see some of the other answers). This makes prime factorization a key component in cryptography.
The long story short, is that you must define a function like the ones mentioned above, or you must import one. For example, sympy.isprime() is a highly optimized function that probably runs much faster. Of course, if you are going to import the amazing number theory package, why not just do:
import sympy
def legendre_n(n):
count = 0
for _ in sympy.primerange(n**2,(n+1)**2+1):
count += 1
return count
You only need is make a identifier of prime numbers.
you can try this:
def isprime(n):
for i in range(2,n):
if(n%i)==0:return False
return True
def legendre_n(n):
"""Returns the number of primes between n**2 and (n+1)**2"""
count = 0
for i in range(n**2, ((n+1)**2)):
if isprime(i):
count += 1
return count
SPOILER ALERT! THIS MAY INFLUENCE YOUR ANSWER TO PROJECT EULER #3
I managed to get a working piece of code but it takes forever to compute the solution because of the large number I am analyzing.
I guess brute force is not the right way...
Any help in making this code more efficient?
# What is the largest prime factor of the number 600851475143
# Set variables
number = 600851475143
primeList = []
primeFactorList = []
# Make list of prime numbers < 'number'
for x in range(2, number+1):
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
primeList.append(x)
# Iterate over primeList to check for prime factors of 'number'
for i in primeList:
if number % i == 0:
primeFactorList.append(i)
# Print largest prime factor of 'number'
print(max(primeFactorList))
I'll first just address some basic problems in the particular algorithm you attempted:
You don't need to pre-generate the primes. Generate them on the fly as you need them - and you'll also see that you were generating way more primes than you need (you only need to try the primes up to sqrt(600851475143))
# What is the largest prime factor of the number 600851475143
# Set variables
number = 600851475143
primeList = []
primeFactorList = []
def primeList():
# Make list of prime numbers < 'number'
for x in range(2, number+1):
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
# Iterate over primeList to check for prime factors of 'number'
for i in primeList():
if i > number**0.5:
break
if number % i == 0:
primeFactorList.append(i)
# Print largest prime factor of 'number'
print(max(primeFactorList))
By using a generator (see the yield?) PrimeList() could even just return prime numbers forever by changing it to:
def primeList():
x = 2
while True:
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
x += 1
Although I can't help but optimize it slightly to skip over even numbers greater than 2:
def primeList():
yield 2
x = 3
while True:
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
x += 2
If you abandon your initial idea of enumerating the primes and trying them one at a time against number, there is an alternative: Instead deal directly with number and factor it out -- i.e., doing what botengboteng suggests and breaking down the number directly.
This will be much faster because we're now checking far fewer numbers:
number = 600851475143
def factors(num):
factors = []
if num % 2 == 0:
factors.append(2)
while num % 2 == 0:
num = num // 2
for f in range(3, int(num**0.5)+1, 2):
if num % f == 0:
factors.append(f)
while num % f == 0:
num = num // f
# Don't keep going if we're dividing by potential factors
# bigger than what is left.
if f > num:
break
if num > 1:
factors.append(num)
return factors
# grab last factor for maximum.
print(factors(number)[-1])
You can use user defined function such as
def isprime(n):
if n < 2:
return False
for i in range(2,(n**0.5)+1):
if n % i == 0:
return False
return True
it will return boolean values. You can use this function for verifying prime factors.
OR
you can continuously divide the number by 2 first
n = 600851475143
while n % 2 == 0:
print(2),
n = n / 2
n has to be odd now skip 2 in for loop, then print every divisor
for i in range(3,n**0.5+1,2):
while n % i== 0:
print(i)
n = n / i
at this point, n will be equal to 1 UNLESS n is a prime. So
if n > 1:
print(n)
to print itself as the prime factor.
Have fun exploring
First calculate the sqrt of your number as you've done.
number = 600851475143
number_sqrt = (number**0.5)+1
Then in your outermost loop only search for the prime numbers with a value less than the sqrt root of your number. You will not need any prime number greater than that. (You can infer any greater based on your list).
for x in range(2, number_sqrt+1):
To infer the greatest factor just divide your number by the items in the factor list including any combinations between them and determine if the resultant is or is not a prime.
No need to recalculate your list of prime numbers. But do define a function for determining if a number is prime or not.
I hope I was clear. Good Luck. Very interesting question.
I made this code, everything is explained if you have questions feel free to comment it
def max_prime_divisor_of(n):
for p in range(2, n+1)[::-1]: #We try to find the max prime who divides it, so start descending
if n%p is not 0: #If it doesn't divide it does not matter if its prime, so skip it
continue
for i in range(3, int(p**0.5)+1, 2): #Iterate over odd numbers
if p%i is 0:
break #If is not prime, skip it
if p%2 is 0: #If its multiple of 2, skip it
break
else: #If it didn't break it, is prime and divide our number, we got it
return p #return it
continue #If it broke, means is not prime, instead is just a non-prime divisor, skip it
If you don't know: What it does in range(2, n+1)[::-1] is the same as reversed(range(2, n+1)) so it means that instead of starting with 2, it starts with n because we are searching the max prime. (Basically it reverses the list to start that way)
Edit 1: This code runs faster the more divisor it has, otherwise is incredibly slow, for general purposes use the code above
def max_prime_divisor_of(n): #Decompose by its divisor
while True:
try:
n = next(n//p for p in range(2, n) if n%p is 0) #Decompose with the first divisor that we find and repeat
except StopIteration: #If the number doesn't have a divisor different from itself and 1, means its prime
return n
If you don't know: What it does in next(n//p for p in range(2, n) if n%p is 0) is that gets the first number who is divisor of n
I know that python is "slow as dirt", but i would like to make a fast and efficient program that finds primes. This is what i have:
num = 5 #Start at five, 2 and 3 are printed manually and 4 is a multiple of 2
print("2")
print("3")
def isPrime(n):
#It uses the fact that a prime (except 2 and 3) is of form 6k - 1 or 6k + 1 and looks only at divisors of this form.
i = 5
w = 2
while (i * i <= n): #You only need to check up too the square root of n
if (n % i == 0): #If n is divisable by i, it is not a prime
return False
i += w
w = 6 - w
return True #If it isnĀ“t ruled out by now, it is a prime
while True:
if ((num % 2 != 0) and (num % 3 != 0)): #save time, only run the function of numbers that are not multiples of 2 or 3
if (isPrime(num) == True):
print(num) #print the now proved prime out to the screen
num += 2 #You only need to check odd numbers
Now comes my questions:
-Does this print out ALL prime numbers?
-Does this print out any numbers that aren't primes?
-Are there more efficient ways(there probably are)?
-How far will this go(limitations of python), and are there any ways to increase upper limit?
Using python 2.7.12
Does this print out ALL prime numbers?
There are infinitely many primes, as demonstrated by Euclid around 300 BC. So the answer to that question is most likely no.
Does this print out any numbers that aren't primes?
By the looks of it, it doesn't. However, to be sure; why not write a unit test?
Are there more efficient ways(there probably are)? -How far will this go(limitations of python), and are there any ways to increase upper limit?
See Fastest way to list all primes below N or Finding the 10001st prime - how to optimize?
Checking for num % 2 != 0 even though you increment by 2 each time seems pointless.
I have found that this algorithm is faster:
primes=[]
n=3
print("2")
while True:
is_prime=True
for prime in primes:
if n % prime ==0:
is_prime=False
break
if prime*prime>n:
break
if is_prime:
primes.append(n)
print (n)
n+=2
This is very simple. The function below returns True if num is a prime, otherwise False. Here, if we find a factor, other than 1 and itself, then we early stop the iterations because the number is not a prime.
def is_this_a_prime(num):
if num < 2 : return False # primes must be greater than 1
for i in range(2,num): # for all integers between 2 and num
if(num % i == 0): # search if num has a factor other than 1 and itself
return False # if it does break, no need to search further, return False
return True # if it doesn't we reached that point, so num is a prime, return True
I tried to optimize the code a bit, and this is what I've done.Instead of running the loop for n or n/2 times, I've done it using a conditional statements.(I think it's a bit faster)
def prime(num1, num2):
import math
def_ = [2,3,5,7,11]
result = []
for i in range(num1, num2):
if i%2!=0 and i%3!=0 and i%5!=0 and i%7!=0 and i%11!=0:
x = str(math.sqrt(i)).split('.')
if int(x[1][0]) > 0:
result.append(i)
else:
continue
return def_+result if num1 < 12 else result