This question already has answers here:
Fastest way to list all primes below N
(39 answers)
Closed 6 years ago.
I have written the following block of code to calculate the sum of all the primes below a certain number-2 000 000 in this case to be precise, however it takes quite some time to execute; 20 second:
def summation_of_primes_below_n(n):
list = []
sum = 0
for i in range(2, n):
if checks_if_prime(i) == True:
list.append(i)
return list
for j in list:
sum = sum + j
return sum
def checks_if_prime(n):
if n == 2:
return True
import math
for i in range(2, math.ceil(math.sqrt(n))+1):
if n%i == 0:
return False
elif i == math.ceil(math.sqrt(n)):
return True
print(summation_of_primes_below_n(2000000))
So I was wondering if there was a way to make my code more efficient. I would greatly appreciate suitable advice on the same. Also, I would prefer that you give more basic solutions since I am a beginner and provide the logic for the same. Thanks a lot!
You can start off by implementing some better algorithm. For eg: Sieve of Eratosthenes
Or if you are happy with your current logic, then few optimizations that can help:
Check only for odd numbers:
for i in range(3, n, 2):
Check only for numbers of form 6n+1, 6n+5
You don't need to do this check : elif i == math.ceil(math.sqrt(n)): for each iteration. If the control reached beyond the loop then the number is prime
You can convert your check_prime to generator pattern. Could save some redundancy and possibly improve locality of reference.
Related
This question already has answers here:
Algorithm to check if a number if a perfect number
(4 answers)
Closed 3 years ago.
I am trying to find perfect number with using a function in python but I want to do this without using any parameters in function and using double for loop.
I wonder that if it is possible. My example code is under the below. I would appreciate it if you help.
def perfectnumber():
sum = 0
#These numbers going to be our numbers which will be divided.
for j in range(1,1001):
#These numbers going to be our numbers which will divide first loop numbers(j)
for k in range(1,1001):
import math
def divisors(n):
divs = [1]
for i in range(2,int(math.sqrt(n))+1):
if n%i == 0:
divs.extend([i,n/i])
return list(set(divs))
def is_perfect_number(n):
return n == sum(divisors(n))
res = []
for i in range(2,1001):
if is_perfect_number(i):
res.append(i)
print(res)
I want to find the largest prime number within range(old_number + 1 , 2*old_number)
This is my code so far:
def get_nearest_prime(self, old_number):
for num in range(old_number + 1, 2 * old_number) :
for i in range(2,num):
if num % i == 0:
break
return num
when I call the get_nearest_prime(13)
the correct output should be 23, while my result was 25.
Anyone can help me to solve this problem? Help will be appreciated!
There are lots of changes you could make, but which ones you should make depend on what you want to accomplish. The biggest problem with your code as it stands is that you're successfully identifying primes with the break and then not doing anything with that information. Here's a minimal change that does roughly the same thing.
def get_nearest_prime(old_number):
largest_prime = 0
for num in range(old_number + 1, 2 * old_number) :
for i in range(2,num):
if num % i == 0:
break
else:
largest_prime = num
return largest_prime
We're using the largest_prime local variable to keep track of all the primes you find (since you iterate through them in increasing order). The else clause is triggered any time you exit the inner for loop "normally" (i.e., without hitting the break clause). In other words, any time you've found a prime.
Here's a slightly faster solution.
import numpy as np
def seive(n):
mask = np.ones(n+1)
mask[:2] = 0
for i in range(2, int(n**.5)+1):
if not mask[i]:
continue
mask[i*i::i] = 0
return np.argwhere(mask)
def get_nearest_prime(old_number):
try:
n = np.max(seive(2*old_number-1))
if n < old_number+1:
return None
return n
except ValueError:
return None
It does roughly the same thing, but it uses an algorithm called the "Sieve of Eratosthenes" to speed up the finding of primes (as opposed to the "trial division" you're using). It isn't the fastest Sieve in the world, but it's reasonably understandable without too many tweaks.
In either case, if you're calling this a bunch of times you'll probably want to keep track of all the primes you've found since computing them is expensive. Caching is easy and flexible in Python, and there are dozens of ways to make that happen if you do need the speed boost.
Note that I'm not positive the range you've specified always contains a prime. It very well might, and if it does you can get away with a lot shorter code. Something like the following.
def get_nearest_prime(old_number):
return np.max(seive(2*old_number-1))
I don't completely agree with the name you've chosen since the largest prime in that interval is usually not the closest prime to old_number, but I think this is what you're looking for anyway.
You can use a sublist to check if the number is prime, if all(i % n for n in range(2, i)) means that number is prime due to the fact that all values returned from modulo were True, not 0. From there you can append those values to a list called primes and then take the max of that list.
List comprehension:
num = 13
l = [*range(num, (2*num)+1)]
print(max([i for i in l if all([i % n for n in range(2,i)])]))
Expanded:
num = 13
l = [*range(num, (2*num)+1)]
primes = []
for i in l:
if all([i % n for n in range(2, i)]):
primes.append(i)
print(max(primes))
23
Search for the nearest prime number from above using the seive function
def get_nearest_prime(old_number):
return old_number+min(seive(2*old_number-1)-old_number, key=lambda a:a<0)
I'm trying to create a python program to check if a given number "n" is prime or not. I've first created a program that lists the divisors of n:
import math
def factors(n):
i = 2
factlist = []
while i <= n:
if n% i == 0:
factlist.append(i)
i = i + 1
return factlist
factors(100)
Next, I'm trying to use the "for i in" function to say that if p1 (the list of factors of n) only includes n itself, then print TRUE, and if else, print FALSE. This seems really easy, but I cannot get it to work. This is what I've done so far:
def isPrime(n):
p1 = factors(n)
for i in p1:
if factors(n) == int(i):
return True
return False
Any help is appreciated! This is a hw assignment, so it's required to use the list of factors in our prime test. Thanks in advance!
p1 will only have n if if has length 1. It may be worthwhile to add if len(p1)==1 as the conditional instead.
What I did (I actually managed to get it in 1 line) was use [number for number in range (2, num // 2) if num % number == 0]. This gets all the numbers that are factors of num. Then you can check if the length of that list is > 0. (Wouldn't be prime).
I usually do something like this:
primes = [2,3]
def is_prime(num):
if num>primes[-1]:
for i in range(primes[-1]+2, num+1,2):
if all(i%p for p in primes):
primes.append(i)
return num in primes
This method generates a global list of prime numbers as it goes. It uses that list to find other prime numbers. The advantage of this method is fewer calculations the program has to make, especially when there are many repeated calls to the is_prime function for possible prime numbers that are less than the largest number you have previously sent to it.
You can adapt some of the concepts in this function for your HW.
This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 2 years ago.
The code does what is supposed to do for smaller values of n, but I would like to calculate the sum for all primes that are below two million, and that's where the code seems to take an endless amount of time. I am working with PyScripter. Is there any way to make this code more efficient?
def is_prime(a):
return all(a % i for i in range(2, a))
def sum_of_primes(n):
sum = 0
x = 2
while x < n:
if is_prime(x):
sum = sum + x
x = x+1
return sum
def main():
print(sum_of_primes(2000000))
if __name__ == '__main__':
main()
Sieve of Eratosthenes is one of the best algorithm of finding all prime numbers below some number.
Basicly you create a list of booleans with the size of range 2 to whatever number you want. Then you remove all the indexes of each true values index folds. Such as after you start searching list you came across 2 and you update to false all the indexes of 2*n then you jump to 3 then you update all 3*n indexes to false. Then you skip 4 since you have already updated it to false. Then you came to 5 and replace all 5*n to false. End so on. At the and you will get a long list that all true valued indexes are prime number. You can use this list as you want.
A basic algorithm as pointed out by Wikipedia would be:
Let A be an array of Boolean values, indexed by integers 2 to n,
initially all set to true.
for i = 2, 3, 4, ..., not exceeding √n:
if A[i] is true:
for j = i2, i2+i, i2+2i, i2+3i, ..., not exceeding n:
A[j] := false.
Output: all i such that A[i] is true.
I need to find the nth prime number, in the fastest way possible in Ruby or Python:
require "prime"
puts Prime.first(n).join("")
This takes a lot of time for numbers >= 100000.
How do I optimize this code?
Give this a try:-
# Steps
# List first 'n' prime
# Choose the very last one
require "prime"
def nprime(n)
(Prime.first n).last
end
puts nprime(10001)
It gave me the answer preety quick:
$ ruby nprime.rb
104743
You may try this dynamic program in python, this looks up in a dictionary of primes(built dynamically by the program itself), which is initially empty and it gets faster as you find larger primes.
dict = {}
def prime(x):
dict[1] = 2
s = x
if x in dict:
return dict[s]
else:
while s > 0:
if s in dict:
pno = int(dict[s]) + 1
break
s-=1
while s < x:
m = 1
while m <= s:
if pno % dict[m] == 0:
pno+=1
m=1
else:
m+=1
dict[s+1]= pno
s+=1
return dict[x]
initially build the dictionary for lower primes for speeding up higher ones. Example to find the 10000th prime, do the following in python shell ahen running the module:
prime(1000)
prime(5000)
prime(10000)
Prime ruby doc.
require "prime"
Prime::EratosthenesSieve.instance.get_nth_prime(1000000)