Below is my code to find the prime number using Python which is not working. Here the function prime will take an integer as input and return whether its a prime number or not. Could you please sort out the problem and explain it.
def prime(x):
if x == 0 or 1:
return False
elif x == 2:
return True
else:
for n in range(2, x):
if x % n == 0:
return False
else:
return True
I think i have sorted out the first issue, the first "if" statement should be if x == 0 or x == 1. Now what about the rest.
What does your for loop?
if x % n == 0:
return False
else:
return True
which by the way eqals return bool(x % n)
So, you return in first iteration, when n == 2.
The whole for loop equals return bool(x % 2), which simply checks if x is diviseable by 2.
That's not what you want.
So, what do you want?
You want to check if x is not diviseable by any numer from range(2, x).
You know that x is not prime, if you find one n from range(2, x), for which x % n == 0 is True.
You know that x is prime, when there is no n in range(2, x), for which x % n == 0 is True.
When can you say that none of n from range is a divisor of x?
After checking all ns from range!
After is the key here.
After the loop, in which you try to find divisor, you can only tell that x is prime.
I hope you now understand the code others posted without explanation.
Note: alternative syntax
Code others posted is correct. However, in Python there is second way writing the for, using for .. else:
for x in range(2, x):
if x % n == 0:
return False
else:
return True
The problem is that the return true should not happen until the for loop has completed.
what we have in the original code is a cuple of tests for trivial cases (x less than 3)
and then a loop for testing all the larger numbers.
In the loop an attempt is made to divide x by a smaller number (starting with 2) and then if it divides evenly False is returned, if it does not True is returned, that is the mistake, instead of returning true, the loop should be allowed to repeat, and division should be tried again with the next number, and only after the supply of divisors (from the for loop) has been exhausted should true be returned.
here's a fixed version:
def prime(x):
if x <= 1:
return False
elif x == 2:
return True
else:
for n in range(2, x):
if x % n == 0:
return False
return True
Others have commented that the loop need not continue all the way up to x and that stopping at sqrt(x) is sufficient, they are correct. doing that will make it faster in almost all cases.
Another speed up can be had if you have a list of small primes (upto sqrt(x)) - you need only test divisibility by the primes below sqrt(x),and not every integer in that range.
The below code is for finding the prime number from 2 to nth number.
For an example, the below code will print the prime number from 2 to 50 and also it will print the number in between 2 to 5o which is not prime.
import time
i=2
j=2
count=0
while(i<50):
while (i>j):
if (i%j)==0:
count=count+1
j=j+1
else:
j=j+1
if count==0:
print i," is a prime"
else:
print i," is not a prime"
i=i+1
j=2
count=0
time.sleep(2)
Related
This code is meant to output prime numbers within a given range:
def sqrt(n):
return n**0.5
# find primes
def primes(minNum, maxNum):
primes_sum = 0
for i in range(minNum, maxNum):
current_max = int(sqrt(i))
for n in range(2, current_max + 1):
if(i%n == 0):
break
else:
primes_sum += i
print(i)
break
print('\nSum of all primes: ', primes_sum)
primes(10, 20)
However, I get an incorrect output:
11, 13, 15, 17, 19
Does someone know how the 15 manages to appear? I put print statements in the first if statement block to verify that 15 is detected by the if(i%n == 0) condition, and it is, but somehow it still appears in my final output and I can't figure out why.
I made changes to your code. Try in this way:
def sqrt(n):
return n**0.5
# find primes
def primes(minNum, maxNum):
primes_sum = 0
for i in range(minNum, maxNum):
current_max = int(sqrt(i))
#print(current_max)
flag = True
for n in range(2, current_max + 1):
#print(i,n)
if(i%n == 0):
flag = False
if flag:
print(i)
primes_sum += i
print('\nSum of all primes: ', primes_sum)
primes(10, 200)
In your code, you are not checking whether all the number is divisible by all the numbers. It will fail for all the odd non-prime numbers as it will check whether it is divisible by 2, if not it is a prime number
This logic:
for n in range(2, current_max + 1):
if(i%n == 0):
break
else:
primes_sum += i
print(i)
break
doesn't work to detect prime numbers, because if the first value of n you test (which will be 2) isn't a factor, you'll immediately count it as a prime and break the loop. You need to finish iterating over the entire range before deciding a number is a prime:
for n in range(2, current_max + 1):
if i % n == 0:
break
else:
primes_sum += i
print(i)
Note that the else is part of the for, not the if -- it only executes if the for loop exhausts itself without ever hitting a break (i.e. if it doesn't find any n values that are factors of i).
The reason is perfectly explained by #SAI SANTOSH CHIRAG. I won't copy that. I'm not sure why you're using sqrt of a number. You can do the stuff without sqrt. You would get wrong output if you use sqrt. In your case, if we check for sqrt of 18, then int of it would be 4 and the divisibility is checked from 2 to 4 whereas 18 is also divisible by 6. I am designing a new code without sqrt and explaining it as well.
My logic: define a function that takes upper bound and lower bound as parameter. Take a for loop ranging from lower bound to upper bound. Now each value will be a number between the range. We've to check whether the number is prime. Use loop ranging from 2 to number and check whether it is divisible or not. If yes, it is not prime. If no, add it to sum. Your code:
def primes(low,upp):
su=[]
for i in range(low,upp+1):
f=True
for j in range(2,i):
if i%j==0:
f=False
if f:
su.append(i)
return su,sum(su)
print(primes(10,20))
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
This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 7 years ago.
I have been trying to write a program that will take an imputed number, and check and see if it is a prime number. The code that I have made so far works perfectly if the number is in fact a prime number. If the number is not a prime number it acts strange. I was wondering if anyone could tell me what the issue is with the code.
a=2
num=13
while num > a :
if num%a==0 & a!=num:
print('not prime')
a=a+1
else:
print('prime')
a=(num)+1
The result given when 24 is imputed is:
not prime
not prime
not prime
prime
How would I fix the error with the reporting prime on every odd and not prime for every even?
You need to stop iterating once you know a number isn't prime. Add a break once you find prime to exit the while loop.
Making only minimal changes to your code to make it work:
a=2
num=13
while num > a :
if num%a==0 & a!=num:
print('not prime')
break
i += 1
else: # loop not exited via break
print('prime')
Your algorithm is equivalent to:
for a in range(a, num):
if a % num == 0:
print('not prime')
break
else: # loop not exited via break
print('prime')
If you throw it into a function you can dispense with break and for-else:
def is_prime(n):
for i in range(3, n):
if n % i == 0:
return False
return True
Even if you are going to brute-force for prime like this you only need to iterate up to the square root of n. Also, you can skip testing the even numbers after two.
With these suggestions:
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
for i in range(3, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
Note that this code does not properly handle 0, 1, and negative numbers.
We make this simpler by using all with a generator expression to replace the for-loop.
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))
def isprime(n):
'''check if integer n is a prime'''
# make sure n is a positive integer
n = abs(int(n))
# 0 and 1 are not primes
if n < 2:
return False
# 2 is the only even prime number
if n == 2:
return True
# all other even numbers are not primes
if not n & 1:
return False
# range starts with 3 and only needs to go up
# the square root of n for all odd numbers
for x in range(3, int(n**0.5) + 1, 2):
if n % x == 0:
return False
return True
Taken from:
http://www.daniweb.com/software-development/python/code/216880/check-if-a-number-is-a-prime-number-python
def is_prime(n):
return all(n%j for j in xrange(2, int(n**0.5)+1)) and n>1
The two main problems with your code are:
After designating a number not prime, you continue to check the rest of the divisors even though you already know it is not prime, which can lead to it printing "prime" after printing "not prime". Hint: use the `break' statement.
You designate a number prime before you have checked all the divisors you need to check, because you are printing "prime" inside the loop. So you get "prime" multiple times, once for each divisor that doesn't go evenly into the number being tested. Hint: use an else clause with the loop to print "prime" only if the loop exits without breaking.
A couple pretty significant inefficiencies:
You should keep track of the numbers you have already found that are prime and only divide by those. Why divide by 4 when you have already divided by 2? If a number is divisible by 4 it is also divisible by 2, so you would have already caught it and there is no need to divide by 4.
You need only to test up to the square root of the number being tested because any factor larger than that would need to be multiplied with a number smaller than that, and that would already have been tested by the time you get to the larger one.
This example is use reduce(), but slow it:
def makepnl(pnl, n):
for p in pnl:
if n % p == 0:
return pnl
pnl.append(n)
return pnl
def isprime(n):
return True if n == reduce(makepnl, range(3, n + 1, 2), [2])[-1] else False
for i in range(20):
print i, isprime(i)
It use Sieve Of Atkin, faster than above:
def atkin(limit):
if limit > 2:
yield 2
if limit > 3:
yield 3
import math
is_prime = [False] * (limit + 1)
for x in range(1,int(math.sqrt(limit))+1):
for y in range(1,int(math.sqrt(limit))+1):
n = 4*x**2 + y**2
if n<=limit and (n%12==1 or n%12==5):
# print "1st if"
is_prime[n] = not is_prime[n]
n = 3*x**2+y**2
if n<= limit and n%12==7:
# print "Second if"
is_prime[n] = not is_prime[n]
n = 3*x**2 - y**2
if x>y and n<=limit and n%12==11:
# print "third if"
is_prime[n] = not is_prime[n]
for n in range(5,int(math.sqrt(limit))):
if is_prime[n]:
for k in range(n**2,limit+1,n**2):
is_prime[k] = False
for n in range(5,limit):
if is_prime[n]: yield n
def isprime(n):
r = list(atkin(n+1))
if not r: return False
return True if n == r[-1] else False
for i in range(20):
print i, isprime(i)
Your problem is that the loop continues to run even thought you've "made up your mind" already. You should add the line break after a=a+1
After you determine that a number is composite (not prime), your work is done. You can exit the loop with break.
while num > a :
if num%a==0 & a!=num:
print('not prime')
break # not going to update a, going to quit instead
else:
print('prime')
a=(num)+1
Also, you might try and become more familiar with some constructs in Python. Your loop can be shortened to a one-liner that still reads well in my opinion.
any(num % a == 0 for a in range(2, num))
Begginer here, so please let me know if I am way of, but I'd do it like this:
def prime(n):
count = 0
for i in range(1, (n+1)):
if n % i == 0:
count += 1
if count > 2:
print "Not a prime"
else:
print "A prime"
This would do the job:
number=int(raw_input("Enter a number to see if its prime:"))
if number <= 1:
print "number is not prime"
else:
a=2
check = True
while a != number:
if number%a == 0:
print "Number is not prime"
check = False
break
a+=1
if check == True:
print "Number is prime"
a=input("Enter number:")
def isprime():
total=0
factors=(1,a)# The only factors of a number
pfactors=range(1,a+1) #considering all possible factors
if a==1 or a==0:# One and Zero are not prime numbers
print "%d is NOT prime"%a
elif a==2: # Two is the only even prime number
print "%d is prime"%a
elif a%2==0:#Any even number is not prime except two
print "%d is NOT prime"%a
else:#a number is prime if its multiples are 1 and itself
#The sum of the number that return zero moduli should be equal to the "only" factors
for number in pfactors:
if (a%number)==0:
total+=number
if total!=sum(factors):
print "%d is NOT prime"%a
else:
print "%d is prime"%a
isprime()
This is a slight variation in that it keeps track of the factors.
def prime(a):
list=[]
x=2
b=True
while x<a:
if a%x==0:
b=False
list.append(x)
x+=1
if b==False:
print "Not Prime"
print list
else:
print "Prime"
max=int(input("Find primes upto what numbers?"))
primeList=[]
for x in range(2,max+1):
isPrime=True
for y in range(2,int(x**0.5)+1) :
if x%y==0:
isPrime=False
break
if isPrime:
primeList.append(x)
print(primeList)
Prime number check.
def is_prime(x):
if x < 2:
return False
else:
if x == 2:
return True
else:
for i in range(2, x):
if x % i == 0:
return False
return True
x = int(raw_input("enter a prime number"))
print is_prime(x)
# is digit prime? we will see (Coder: Chikak)
def is_prime(x):
flag = False
if x < 2:
return False
else:
for count in range(2, x):
if x % count == 0:
flag = True
break
if flag == True:
return False
return True
I'm getting several incorrect answers in this code. For example, 9 is showing as prime. I'm guessing my problem is with using the breaks, but I can't seem to logically figure out what is wrong with this simple code someone asked me about.
for number in range(0, 1000):
for x in range(2, number):
if (number % x == 0):
break
else:
print x
break
In your script, regardless of if the number is divisble by 2 or not, it breaks the loop immediately.
I've reindented the code and this is probably closer to what you were trying to do.
In your original code, if the number is divisible by 2 (first number in the range(2,number), then you break the loop and if it is not divisible you also break the loop. So all odd numbers, like 9, looked like primes.
The else keyword after a for loop is run iff the loop exits normally. So the "is prime" part will only be printed if no divisor is found.
for number in range(0,1000):
for x in range(2,number):
if(number % x == 0):
print number,"divisible by",x
break
else:
print number, "is prime"
You can see this is anction here: http://codepad.org/XdS413LR
Also, this is a naive algorithm (not a critique of the code, exploring simple algorithms is a useful study), but you can make a little more efficient. Technically you only need to check as far as the sqare root of number, as any number larger than the square root must have a complement that is less than the square root, which should have already been encountered. So the logic in the code can be changed to:
from math import sqrt
for number in range(0,1000):
for x in range(2,int(sqrt(number/2))):
# Rest of code as above.
That said there are many ways that you can optimise the checking or discovery of prime numbers that are worth investigating if you get the chance.
I think you want something like this:
for number in xrange(100):
for i in range(2,number):
if number % i == 0:
break
else:
print number
this iterates through every number form 1-100 and checks if any number is divisible by any # besides one but you need the else: statement out side of the inner for loop so if it goes throught the inner for loop without finding a divisor its prime
Here are some alternatives. First, this checks for primes:
def check_for_prime(n):
if n == 1: return False
elif n == 2: return True
elif n%2 == 0: return False
# Elementary prime test borrowed from oeis.org/A000040.
odds = 3
while odds < n**.5+1:
if n%odds == 0: return False
odds += 2
return True
This is slightly faster, but you should have experience using yield:
def primes_plus():
yield 2
yield 3
i = 5
while True:
yield i
if i % 6 == 1:
i += 2
i += 2
Here are some alternatives.
n is the number till the range you want to find
n=100
for i in range(0,n):
num = filter(lambda y :i % y == 0,(y for y in range(2,(i/2))))
if num or i == 4:
print "%s not a prime number" %(i)
else:
print "%s is a prime number" %(i)
I'm trying (and failing) to write a simple function that checks whether a number is prime. The problem I'm having is that when I get to an if statement, it seems to be doing the same thing regardless of the input. This is the code I have:
def is_prime(x):
if x >= 2:
for i in range(2,x):
if x % i != 0: #if x / i remainder is anything other than 0
print "1"
break
else:
print "ok"
else:
print "2"
else: print "3"
is_prime(13)
The line with the comment is where I'm sure the problem is. It prints "1" regardless of what integer I use as a parameter. I'm sorry for what is probably a stupid question, I'm not an experienced programmer at all.
Your code is actually really close to being functional. You just have a logical error in your conditional.
There are some optimizations you can make for a primality test like only checking up until the square root of the given number.
def is_prime(x):
if x >= 2:
for i in range(2,x):
if x % i == 0: # <----- You need to be checking if it IS evenly
print "not prime" # divisible and break if so since it means
break # the number cannot be prime
else:
print "ok"
else:
print "prime"
else:
print "not prime"
The problem is this line:
if x % i != 0:
You are testing if x % i is not 0, which is true for any pair of integers that are relatively prime (hence, you always get it printed out)
It should be:
if x % i == 0:
This kind of checks can be single expression:
def is_prime(n):
return n>1 and all(n%k for k in range(2,n//2))
Try using return statements instead of (or in addition to) print statements, eg:
from math import sqrt # for a smaller range
def is_prime(x):
if x <= 2:
return True
for i in range(2, int(sqrt(x)) + 1):
if x % i == 0:
print "%d is divisible by %d" % (x,i)
return False
return True
is_prime(13)
True
is_prime(14)
14 is divisible by 2
False