Looping and finding composite/prime numbers and saving it to a set - python

I am trying to loop through a list of values and find out whether each number is either prime or composite and save it in the set under the function. The problem I am having is that it's not finding anything and it's just saving a running count of numbers. For example, this script is just saving all numbers from 1-19. I also understand that it's not actually saving the values in one set but I'll figure that out. Mostly need help on actually getting the values to be prime/composite.
def prime(num):
prime_set = set()
composite_set = set()
for i in range(2,num):
if num % i == 0:
composite_set.update([num])
else:
prime_set.update([num])
return(prime_set)
for num in range(1,20):
print(num,prime(num))

Because of your if/else block in prime, num will be added to prime_set if any number in range(2,num) fails to divide evenly into num. Since num-1 doesn't divide evenly into num whenever num is at least 3, num will always be added to prime_set.
What you want to do is only add num to prime_set if you failed to find any divisors. The simplest change to your code would be.
def prime(num):
prime_set = set()
composite_set = set()
for i in range(2,num):
if num%i == 0:
composite_set.add(num)
break # You don't need to keep searching
if not composite_set: # That is, it's empty.
prime_set.add(num)
return prime_set

You could also consider implementing the Sieve of Erastosthenes algorithm for generating a set of primes which is going to be much faster; it works by continuously eliminating multiples of all primes as they are found:
def primes(n):
# Set prime to true for all values >= 2 initially
primes = [i >= 2 for i in range(n + 1)]
# iterate to set all multiples of the considered prime to composite
p = 2
while (p * p <= n):
if primes[p]:
for i in range(p * 2, n + 1, p):
primes[i] = False
p += 1
# composite_set = set([i for i, p in enumerate(primes) if not p])
prime_set = set([i for i, p in enumerate(primes) if p])
return prime_set
On my machine this algorithm takes less than 200 ms to generate all primes up to 1 million.

Related

Eulers problem №3, code stucks on big numbers

I'm currently learning Python, and practice with euler's problem's.
I'm stuck on 3rd problem, my code didn't working on the big numbers, but with other number's it's working.
n = 600851475143
x = 0
for i in range(2,n):
if(n%i == 0):
if(x < i): x = i
print(x)
The console just didn't get any results and stucks.
P.S https://projecteuler.net/problem=3
(sorry for my bad english)
It's running, but just the time it takes is huge.
You can check by the following code, it keeps going to print x's.
n = 600851475143
x = 0
for i in range(2, n):
if n % i == 0:
if x < i:
x = i
print(x)
To save time, you can try the following code instead of your code:
n = 600851475143
x = 0
for i in range(2, n):
if n % i == 0:
x = n // i
break
print(x)
which prints 8462696833 instantly. But as #seesharper stated on the comment, it is merely the largest factor and not a prime factor. So it is not the correct answer to the Project Euler Problem #3.
Check this code you will save a lot of time
Using sqrt for optimization
from math import sqrt
def Euler3(n):
x=int(sqrt(n))
for i in range(2,x+1):
while n % i == 0:
n //= i
if n == 1 or n == i:
return i
return n
n = int(input())
print(Euler3(n))
Also, check my Euler git repo
There are only 6 solutions in python2 and it's pretty old but they are very well optimized.
from tqdm.auto import tqdm
n = 600851475143
x = 0
for i in tqdm(range(2,n)):
if(n%i == 0):
x = i
print(x)
If using classic python, your program will last for at least 40 min, that's why you had no output. I suggest you either use numpy to go through, or add a step because I think even numbers won't work.
I used tqdm to estimate the time needed for the for loop to run, you can download it using pip install tqdm
What would be more efficient is to only divide your number by actual primes. You also only need to check divisors up to the square root of the number given that any valid (integer) result will be also be a divisor (which you will already have checked if your divisor goes beyond the square root).
# generator to obtain primes up to N
# (sieve of Eratosthenes)
def primes(N):
isPrime = [True]*(N+1)
p = 2
while p<=N:
if isPrime[p]:
yield p
isPrime[p::p] = (False for _ in isPrime[p::p])
p += 1 + p>2
# use the max function on primes up to the square root
# filtered to only include those that divide the number
n = 600851475143
result = max(p for p in primes(int(n**0.5)+1) if n%p == 0)
print(result) # 6857
Alternatively, you can use sequential divisions to find factors while reducing the number as you go along. This will cause each new factor you find to be a prime number because divisions by all smaller numbers will already have been done and removed from the remaining number. It will also greatly reduce the number of iterations when your number has many prime factors.
def primeFactors(N): # prime factors generator
d,d2 = 2,4 # start divisors at first prime (2)
while d2<=N: # no need to go beyond √N
if N%d:
d += 1 + (d&1) # progress by 2 from 3 onward
d2 = d*d # use square of d as limiter
else:
yield d # return prime factor
N //= d # and reduce number
if N>1: yield N # final number could be last factor
print(*primeFactors(600851475143)) # 71 839 1471 6857
print(max(primeFactors(600851475143))) # 6857

Algorithm recommendation for calculating prime factors (Python Beginner)

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

sieve of eratostheness algorithm

I have this function for calculate prime numbers with sieve of eratosthenes. I have one error i don't understand why.
def era1(n):
llista1 = []
llista2 = []
i = 2
while(i<(n+1)):
llista1.append(i)
i = i + 1
while (llista1[0]<(n**0.5)):
llista2.append(llista1[0])
for j in range ((len(llista1))-1):
if (llista1[j] % llista1[0] == 0) : #<------- error list index out of range
llista1.remove(llista1[j])
llista1.remove(llista1[0])
print llista2
This is the result of removing items in a list while iterating through them. You've specified your for loop to run for n amount of times, but by the time you get to the nth item, the item which was once there has been moved back a few indexes because you're removing items from the list.
You'll need to re-think your method in reimplementing the Sieve. I can't 100% follow your approach to it, but I'm sure it might involve having a secondary list. Whitelist, don't blacklist :).
Also, enumerate() is a cool function to look into.
might be useful for anyone that still looking for this algorithm approach
def SieveOfEratosthenes(n):
# Create a boolean array "prime[0..n]" and initialize
# all entries it as true. A value in prime[i] will
# finally be false if i is Not a prime, else true.
prime = [True for i in range(n + 1)]
p = 2
while (p * p <= n):
# If prime[p] is not changed, then it is a prime
if (prime[p] == True):
# Update all multiples of p
for i in range(p * 2, n + 1, p):
prime[i] = False
p += 1
prime[0]= False
prime[1]= False
# Print all prime numbers
for p in range(n + 1):
if prime[p]:
print (p)
# driver program
if __name__=='__main__':
n = 30
print ("Following are the prime numbers smaller")
print ("than or equal to", n )
SieveOfEratosthenes(n)

I can't find where I did wrong :(

I was working on project euler question 23 with python. For this question, I have to find sum of any numbers <28124 that cannot be made by sum of two abundant numbers. abundant numbers are numbers that are smaller then its own sum of proper divisors.
my apporach was : https://gist.github.com/anonymous/373f23098aeb5fea3b12fdc45142e8f7
from math import sqrt
def dSum(n): #find sum of proper divisors
lst = set([])
if n%2 == 0:
step = 1
else:
step = 2
for i in range(1, int(sqrt(n))+1, step):
if n % i == 0:
lst.add(i)
lst.add(int(n/i))
llst = list(lst)
lst.remove(n)
sum = 0
for j in lst:
sum += j
return sum
#any numbers greater than 28123 can be written as the sum of two abundant numbers.
#thus, only have to find abundant numbers up to 28124 / 2 = 14062
abnum = [] #list of abundant numbers
sum = 0
can = set([])
for i in range(1,14062):
if i < dSum(i):
abnum.append(i)
for i in abnum:
for j in abnum:
can.add(i + j)
print (abnum)
print (can)
cannot = set(range(1,28124))
cannot = cannot - can
cannot = list(cannot)
cannot.sort ()
result = 0
print (cannot)
for i in cannot:
result += i
print (result)
which gave me answer of 31531501, which is wrong.
I googled the answer and answer should be 4179871.
theres like 1 million difference between the answers, so it should mean that I'm removing numbers that cannot be written as sum of two abundant numbers. But when I re-read the code it looks fine logically...
Please save from this despair
Just for some experience you really should look at comprehensions and leveraging the builtins (vs. hiding them):
You loops outside of dSum() (which can also be simplified) could look like:
import itertools as it
abnum = [i for i in range(1,28124) if i < dSum(i)]
can = {i+j for i, j in it.product(abnum, repeat=2)}
cannot = set(range(1,28124)) - can
print(sum(cannot)) # 4179871
There are a few ways to improve your code.
Firstly, here's a more compact version of dSum that's fairly close to your code. Operators are generally faster than function calls, so I use ** .5 instead of calling math.sqrt. I use a conditional expression instead of an if...else block to compute the step size. I use the built-in sum function instead of a for loop to add up the divisors; also, I use integer subtraction to remove n from the total because that's more efficient than calling the set.remove method.
def dSum(n):
lst = set()
for i in range(1, int(n ** .5) + 1, 2 if n % 2 else 1):
if n % i == 0:
lst.add(i)
lst.add(n // i)
return sum(lst) - n
However, we don't really need to use a set here. We can just add the divisor pairs as we find them, if we're careful not to add any divisor twice.
def dSum(n):
total = 0
for i in range(1, int(n ** .5) + 1, 2 if n % 2 else 1):
if n % i == 0:
j = n // i
if i < j:
total += i + j
else:
if i == j:
total += i
break
return total - n
This is slightly faster, and uses less RAM, at the expense of added code complexity. However, there's a more efficient approach to this problem.
Instead of finding the divisors (and hence the divisor sum) of each number individually, it's better to use a sieving approach that finds the divisors of all the numbers in the required range. Here's a simple example.
num = 28124
# Build a table of divisor sums.
table = [1] * num
for i in range(2, num):
for j in range(2 * i, num, i):
table[j] += i
# Collect abundant numbers
abnum = [i for i in range(2, num) if i < table[i]]
print(len(abnum), abnum[0], abnum[-1])
output
6965 12 28122
If we need to find divisor sums for a very large num a good approach is to find the prime power factors of each number, since there's an efficient way to compute the sum of the divisors from the prime power factorization. However, for numbers this small the minor time saving doesn't warrant the extra code complexity. (But I can add some prime power sieve code if you're curious; for finding divisor sums for all numbers < 28124, the prime power sieve technique is about twice as fast as the above code).
AChampion's answer shows a very compact way to find the sum of the numbers that cannot be written as the sum of two abundant numbers. However, it's a bit slow, mostly because it loops over all pairs of abundant numbers in abnum. Here's a faster way.
def main():
num = 28124
# Build a table of divisor sums. table[0] should be 0, but we ignore it.
table = [1] * num
for i in range(2, num):
for j in range(2 * i, num, i):
table[j] += i
# Collect abundant numbers
abnum = [i for i in range(2, num) if i < table[i]]
del table
# Create a set for fast searching
abset = set(abnum)
print(len(abset), abnum[0], abnum[-1])
total = 0
for i in range(1, num):
# Search for pairs of abundant numbers j <= d: j + d == i
for j in abnum:
d = i - j
if d < j:
# No pairs were found
total += i
break
if d in abset:
break
print(total)
if __name__ == "__main__":
main()
output
6965 12 28122
4179871
This code runs in around 2.7 seconds on my old 32bit single core 2GHz machine running Python 3.6.0. On Python 2, it's about 10% faster; I think that's because list comprehensions have less overhead in Python 2 (the run in the current scope rather than creating a new scope).

Beginner looking for advice/help on this code (Python) [duplicate]

I was having issues in printing a series of prime numbers from one to hundred. I can't figure our what's wrong with my code.
Here's what I wrote; it prints all the odd numbers instead of primes:
for num in range(1, 101):
for i in range(2, num):
if num % i == 0:
break
else:
print(num)
break
You need to check all numbers from 2 to n-1 (to sqrt(n) actually, but ok, let it be n).
If n is divisible by any of the numbers, it is not prime. If a number is prime, print it.
for num in range(2,101):
prime = True
for i in range(2,num):
if (num%i==0):
prime = False
if prime:
print (num)
You can write the same much shorter and more pythonic:
for num in range(2,101):
if all(num%i!=0 for i in range(2,num)):
print (num)
As I've said already, it would be better to check divisors not from 2 to n-1, but from 2 to sqrt(n):
import math
for num in range(2,101):
if all(num%i!=0 for i in range(2,int(math.sqrt(num))+1)):
print (num)
For small numbers like 101 it doesn't matter, but for 10**8 the difference will be really big.
You can improve it a little more by incrementing the range you check by 2, and thereby only checking odd numbers. Like so:
import math
print 2
for num in range(3,101,2):
if all(num%i!=0 for i in range(2,int(math.sqrt(num))+1)):
print (num)
Edited:
As in the first loop odd numbers are selected, in the second loop no
need to check with even numbers, so 'i' value can be start with 3 and
skipped by 2.
import math
print 2
for num in range(3,101,2):
if all(num%i!=0 for i in range(3,int(math.sqrt(num))+1, 2)):
print (num)
I'm a proponent of not assuming the best solution and testing it. Below are some modifications I did to create simple classes of examples by both #igor-chubin and #user448810. First off let me say it's all great information, thank you guys. But I have to acknowledge #user448810 for his clever solution, which turns out to be the fastest by far (of those I tested). So kudos to you, sir! In all examples I use a values of 1 million (1,000,000) as n.
Please feel free to try the code out.
Good luck!
Method 1 as described by Igor Chubin:
def primes_method1(n):
out = list()
for num in range(1, n+1):
prime = True
for i in range(2, num):
if (num % i == 0):
prime = False
if prime:
out.append(num)
return out
Benchmark: Over 272+ seconds
Method 2 as described by Igor Chubin:
def primes_method2(n):
out = list()
for num in range(1, n+1):
if all(num % i != 0 for i in range(2, num)):
out.append(num)
return out
Benchmark: 73.3420000076 seconds
Method 3 as described by Igor Chubin:
def primes_method3(n):
out = list()
for num in range(1, n+1):
if all(num % i != 0 for i in range(2, int(num**.5 ) + 1)):
out.append(num)
return out
Benchmark: 11.3580000401 seconds
Method 4 as described by Igor Chubin:
def primes_method4(n):
out = list()
out.append(2)
for num in range(3, n+1, 2):
if all(num % i != 0 for i in range(2, int(num**.5 ) + 1)):
out.append(num)
return out
Benchmark: 8.7009999752 seconds
Method 5 as described by user448810 (which I thought was quite clever):
def primes_method5(n):
out = list()
sieve = [True] * (n+1)
for p in range(2, n+1):
if (sieve[p]):
out.append(p)
for i in range(p, n+1, p):
sieve[i] = False
return out
Benchmark: 1.12000012398 seconds
Notes: Solution 5 listed above (as proposed by user448810) turned out to be the fastest and honestly quiet creative and clever. I love it. Thanks guys!!
EDIT: Oh, and by the way, I didn't feel there was any need to import the math library for the square root of a value as the equivalent is just (n**.5). Otherwise I didn't edit much other then make the values get stored in and output array to be returned by the class. Also, it would probably be a bit more efficient to store the results to a file than verbose and could save a lot on memory if it was just one at a time but would cost a little bit more time due to disk writes. I think there is always room for improvement though. So hopefully the code makes sense guys.
2021 EDIT: I know it's been a really long time but I was going back through my Stackoverflow after linking it to my Codewars account and saw my recently accumulated points, which which was linked to this post. Something I read in the original poster caught my eye for #user448810, so I decided to do a slight modification mentioned in the original post by filtering out odd values before appending the output array. The results was much better performance for both the optimization as well as latest version of Python 3.8 with a result of 0.723 seconds (prior code) vs 0.504 seconds using 1,000,000 for n.
def primes_method5(n):
out = list()
sieve = [True] * (n+1)
for p in range(2, n+1):
if (sieve[p] and sieve[p]%2==1):
out.append(p)
for i in range(p, n+1, p):
sieve[i] = False
return out
Nearly five years later, I might know a bit more but I still just love Python, and it's kind of crazy to think it's been that long. The post honestly feels like it was made a short time ago and at the time I had only been using python about a year I think. And it still seems relevant. Crazy. Good times.
Instead of trial division, a better approach, invented by the Greek mathematician Eratosthenes over two thousand years ago, is to sieve by repeatedly casting out multiples of primes.
Begin by making a list of all numbers from 2 to the maximum desired prime n. Then repeatedly take the smallest uncrossed number and cross out all of its multiples; the numbers that remain uncrossed are prime.
For example, consider the numbers less than 30. Initially, 2 is identified as prime, then 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 and 30 are crossed out. Next 3 is identified as prime, then 6, 9, 12, 15, 18, 21, 24, 27 and 30 are crossed out. The next prime is 5, so 10, 15, 20, 25 and 30 are crossed out. And so on. The numbers that remain are prime: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29.
def primes(n):
sieve = [True] * (n+1)
for p in range(2, n+1):
if (sieve[p]):
print p
for i in range(p, n+1, p):
sieve[i] = False
An optimized version of the sieve handles 2 separately and sieves only odd numbers. Also, since all composites less than the square of the current prime are crossed out by smaller primes, the inner loop can start at p^2 instead of p and the outer loop can stop at the square root of n. I'll leave the optimized version for you to work on.
break ends the loop that it is currently in. So, you are only ever checking if it divisible by 2, giving you all odd numbers.
for num in range(2,101):
for i in range(2,num):
if (num%i==0):
break
else:
print(num)
that being said, there are much better ways to find primes in python than this.
for num in range(2,101):
if is_prime(num):
print(num)
def is_prime(n):
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
The best way to solve the above problem would be to use the "Miller Rabin Primality Test" algorithm. It uses a probabilistic approach to find if a number is prime or not. And it is by-far the most efficient algorithm I've come across for the same.
The python implementation of the same is demonstrated below:
def miller_rabin(n, k):
# Implementation uses the Miller-Rabin Primality Test
# The optimal number of rounds for this test is 40
# See http://stackoverflow.com/questions/6325576/how-many-iterations-of-rabin-miller-should-i-use-for-cryptographic-safe-primes
# for justification
# If number is even, it's a composite number
if n == 2:
return True
if n % 2 == 0:
return False
r, s = 0, n - 1
while s % 2 == 0:
r += 1
s //= 2
for _ in xrange(k):
a = random.randrange(2, n - 1)
x = pow(a, s, n)
if x == 1 or x == n - 1:
continue
for _ in xrange(r - 1):
x = pow(x, 2, n)
if x == n - 1:
break
else:
return False
return True
Igor Chubin's answer can be improved. When testing if X is prime, the algorithm doesn't have to check every number up to the square root of X, it only has to check the prime numbers up to the sqrt(X). Thus, it can be more efficient if it refers to the list of prime numbers as it is creating it. The function below outputs a list of all primes under b, which is convenient as a list for several reasons (e.g. when you want to know the number of primes < b). By only checking the primes, it saves time at higher numbers (compare at around 10,000; the difference is stark).
from math import sqrt
def lp(b)
primes = [2]
for c in range(3,b):
e = round(sqrt(c)) + 1
for d in primes:
if d <= e and c%d == 0:
break
else:
primes.extend([c])
return primes
My way of listing primes to an entry number without too much hassle is using the property that you can get any number that is not a prime with the summation of primes.
Therefore, if you divide the entry number with all primes below it, and it is not evenly divisible by any of them, you know that you have a prime.
Of course there are still faster ways of getting the primes, but this one already performs quite well, especially because you are not dividing the entry number by any number, but quite only the primes all the way to that number.
With this code I managed on my computer to list all primes up to 100 000 in less than 4 seconds.
import time as t
start = t.clock()
primes = [2,3,5,7]
for num in xrange(3,100000,2):
if all(num%x != 0 for x in primes):
primes.append(num)
print primes
print t.clock() - start
print sum(primes)
A Python Program function module that returns the 1'st N prime numbers:
def get_primes(count):
"""
Return the 1st count prime integers.
"""
result = []
x=2
while len(result) in range(count):
i=2
flag=0
for i in range(2,x):
if x%i == 0:
flag+=1
break
i=i+1
if flag == 0:
result.append(x)
x+=1
pass
return result
A simpler and more efficient way of solving this is storing all prime numbers found previously and checking if the next number is a multiple of any of the smaller primes.
n = 1000
primes = [2]
for i in range(3, n, 2):
if not any(i % prime == 0 for prime in primes):
primes.append(i)
print(primes)
Note that any is a short circuit function, in other words, it will break the loop as soon as a truthy value is found.
we can make a list of prime numbers using sympy library
import sympy
lower=int(input("lower value:")) #let it be 30
upper=int(input("upper value:")) #let it be 60
l=list(sympy.primerange(lower,upper+1)) #[31,37,41,43,47,53,59]
print(l)
Here's a simple and intuitive version of checking whether it's a prime in a RECURSIVE function! :) (I did it as a homework assignment for an MIT class)
In python it runs very fast until 1900. IF you try more than 1900, you'll get an interesting error :) (Would u like to check how many numbers your computer can manage?)
def is_prime(n, div=2):
if div> n/2.0: return True
if n% div == 0:
return False
else:
div+=1
return is_prime(n,div)
#The program:
until = 1000
for i in range(until):
if is_prime(i):
print i
Of course... if you like recursive functions, this small code can be upgraded with a dictionary to seriously increase its performance, and avoid that funny error.
Here's a simple Level 1 upgrade with a MEMORY integration:
import datetime
def is_prime(n, div=2):
global primelist
if div> n/2.0: return True
if div < primelist[0]:
div = primelist[0]
for x in primelist:
if x ==0 or x==1: continue
if n % x == 0:
return False
if n% div == 0:
return False
else:
div+=1
return is_prime(n,div)
now = datetime.datetime.now()
print 'time and date:',now
until = 100000
primelist=[]
for i in range(until):
if is_prime(i):
primelist.insert(0,i)
print "There are", len(primelist),"prime numbers, until", until
print primelist[0:100], "..."
finish = datetime.datetime.now()
print "It took your computer", finish - now , " to calculate it"
Here are the resuls, where I printed the last 100 prime numbers found.
time and date: 2013-10-15 13:32:11.674448
There are 9594 prime numbers, until 100000
[99991, 99989, 99971, 99961, 99929, 99923, 99907, 99901, 99881, 99877, 99871, 99859, 99839, 99833, 99829, 99823, 99817, 99809, 99793, 99787, 99767, 99761, 99733, 99721, 99719, 99713, 99709, 99707, 99689, 99679, 99667, 99661, 99643, 99623, 99611, 99607, 99581, 99577, 99571, 99563, 99559, 99551, 99529, 99527, 99523, 99497, 99487, 99469, 99439, 99431, 99409, 99401, 99397, 99391, 99377, 99371, 99367, 99349, 99347, 99317, 99289, 99277, 99259, 99257, 99251, 99241, 99233, 99223, 99191, 99181, 99173, 99149, 99139, 99137, 99133, 99131, 99119, 99109, 99103, 99089, 99083, 99079, 99053, 99041, 99023, 99017, 99013, 98999, 98993, 98981, 98963, 98953, 98947, 98939, 98929, 98927, 98911, 98909, 98899, 98897] ...
It took your computer 0:00:40.871083 to calculate it
So It took 40 seconds for my i7 laptop to calculate it. :)
# computes first n prime numbers
def primes(n=1):
from math import sqrt
count = 1
plist = [2]
c = 3
if n <= 0 :
return "Error : integer n not >= 0"
while (count <= n - 1): # n - 1 since 2 is already in plist
pivot = int(sqrt(c))
for i in plist:
if i > pivot : # check for primae factors 'till sqrt c
count+= 1
plist.append(c)
break
elif c % i == 0 :
break # not prime, no need to iterate anymore
else :
continue
c += 2 # skipping even numbers
return plist
You are terminating the loop too early. After you have tested all possibilities in the body of the for loop, and not breaking, then the number is prime. As one is not prime you have to start at 2:
for num in xrange(2, 101):
for i in range(2,num):
if not num % i:
break
else:
print num
In a faster solution you only try to divide by primes that are smaller or equal to the root of the number you are testing. This can be achieved by remembering all primes you have already found. Additionally, you only have to test odd numbers (except 2). You can put the resulting algorithm into a generator so you can use it for storing primes in a container or simply printing them out:
def primes(limit):
if limit > 1:
primes_found = [(2, 4)]
yield 2
for n in xrange(3, limit + 1, 2):
for p, ps in primes_found:
if ps > n:
primes_found.append((n, n * n))
yield n
break
else:
if not n % p:
break
for i in primes(101):
print i
As you can see there is no need to calculate the square root, it is faster to store the square for each prime number and compare each divisor with this number.
How about this? Reading all the suggestions I used this:
prime=[2]+[num for num in xrange(3,m+1,2) if all(num%i!=0 for i in range(2,int(math.sqrt(num))+1))]
Prime numbers up to 1000000
root#nfs:/pywork# time python prime.py
78498
real 0m6.600s
user 0m6.532s
sys 0m0.036s
Adding to the accepted answer, further optimization can be achieved by using a list to store primes and printing them after generation.
import math
Primes_Upto = 101
Primes = [2]
for num in range(3,Primes_Upto,2):
if all(num%i!=0 for i in Primes):
Primes.append(num)
for i in Primes:
print i
Here is the simplest logic for beginners to get prime numbers:
p=[]
for n in range(2,50):
for k in range(2,50):
if n%k ==0 and n !=k:
break
else:
for t in p:
if n%t ==0:
break
else:
p.append(n)
print p
n = int(input())
is_prime = lambda n: all( n%i != 0 for i in range(2, int(n**.5)+1) )
def Prime_series(n):
for i in range(2,n):
if is_prime(i) == True:
print(i,end = " ")
else:
pass
Prime_series(n)
Here is a simplified answer using lambda function.
def function(number):
for j in range(2, number+1):
if all(j % i != 0 for i in range(2, j)):
print(j)
function(13)
for i in range(1, 100):
for j in range(2, i):
if i % j == 0:
break
else:
print(i)
Print n prime numbers using python:
num = input('get the value:')
for i in range(2,num+1):
count = 0
for j in range(2,i):
if i%j != 0:
count += 1
if count == i-2:
print i,
def prime_number(a):
yes=[]
for i in range (2,100):
if (i==2 or i==3 or i==5 or i==7) or (i%2!=0 and i%3!=0 and i%5!=0 and i%7!=0 and i%(i**(float(0.5)))!=0):
yes=yes+[i]
print (yes)
min=int(input("min:"))
max=int(input("max:"))
for num in range(min,max):
for x in range(2,num):
if(num%x==0 and num!=1):
break
else:
print(num,"is prime")
break
This is a sample program I wrote to check if a number is prime or not.
def is_prime(x):
y=0
if x<=1:
return False
elif x == 2:
return True
elif x%2==0:
return False
else:
root = int(x**.5)+2
for i in xrange (2,root):
if x%i==0:
return False
y=1
if y==0:
return True
n = int(raw_input('Enter the integer range to find prime no :'))
p = 2
while p<n:
i = p
cnt = 0
while i>1:
if p%i == 0:
cnt+=1
i-=1
if cnt == 1:
print "%s is Prime Number"%p
else:
print "%s is Not Prime Number"%p
p+=1
Using filter function.
l=range(1,101)
for i in range(2,10): # for i in range(x,y), here y should be around or <= sqrt(101)
l = filter(lambda x: x==i or x%i, l)
print l
for num in range(1,101):
prime = True
for i in range(2,num/2):
if (num%i==0):
prime = False
if prime:
print num
f=0
sum=0
for i in range(1,101):
for j in range(1,i+1):
if(i%j==0):
f=f+1
if(f==2):
sum=sum+i
print i
f=0
print sum
The fastest & best implementation of omitting primes:
def PrimeRanges2(a, b):
arr = range(a, b+1)
up = int(math.sqrt(b)) + 1
for d in range(2, up):
arr = omit_multi(arr, d)
Here is a different approach that trades space for faster search time. This may be fastest so.
import math
def primes(n):
if n < 2:
return []
numbers = [0]*(n+1)
primes = [2]
# Mark all odd numbers as maybe prime, leave evens marked composite.
for i in xrange(3, n+1, 2):
numbers[i] = 1
sqn = int(math.sqrt(n))
# Starting with 3, look at each odd number.
for i in xrange(3, len(numbers), 2):
# Skip if composite.
if numbers[i] == 0:
continue
# Number is prime. Would have been marked as composite if there were
# any smaller prime factors already examined.
primes.append(i)
if i > sqn:
# All remaining odd numbers not marked composite must be prime.
primes.extend([i for i in xrange(i+2, len(numbers), 2)
if numbers[i]])
break
# Mark all multiples of the prime as composite. Check odd multiples.
for r in xrange(i*i, len(numbers), i*2):
numbers[r] = 0
return primes
n = 1000000
p = primes(n)
print "Found", len(p), "primes <=", n
Adding my own version, just to show some itertools tricks v2.7:
import itertools
def Primes():
primes = []
a = 2
while True:
if all(itertools.imap(lambda p : a % p, primes)):
yield a
primes.append(a)
a += 1
# Print the first 100 primes
for _, p in itertools.izip(xrange(100), Primes()):
print p

Categories

Resources