Generating prime numbers from 1 to n python3. How to improve efficiency and what is the complexity?









up vote
0
down vote

favorite












Input: A number, max (a large number)
Output: All the primes from 1 to max
Output is in the form of a list and will be [2,3,5,7,11,13,.......]
The code attempts to perform this task in an efficient way (least time complexity).



from math import sqrt 
max = (10**6)*3
print("nThis code prints all primes till: " , max , "n")
list_primes=[2]

def am_i_prime(num):
"""
Input/Parameter the function takes: An integer number
Output: returns True, if the number is prime and False if not
"""
decision=True
i=0
while(list_primes[i] <= sqrt(num)): #Till sqrt(n) to save comparisons
if(num%list_primes[i]==0):
decision=False
break
#break is inserted so that we get out of comparisons faster
#Eg. for 1568, we should break from the loop as soon as we know that 1568%2==0
i+=1
return decision


for i in range(3,max,2): #starts from 3 as our list contains 2 from the beginning
if am_i_prime(i)==True:
list_primes.append(i) #if a number is found to be prime, we append it to our list of primes

print(list_primes)


How can I make this faster? Where can I improve?
What is the time complexity of this code? Which steps are inefficient?
In what ways is the Sieve of Eratosthenes more efficient than this?



Working for the first few iterations:-



  1. We have a list_primes which contains prime numbers. It initially contains only 2.

  2. We go to the next number, 3. Is 3 divisible by any of the numbers in list_primes? No! We append 3 to list_primes. Right now, list_primes=[2,3]

  3. We go to the next number 4. Is 4 divisible by any of the numbers in list_primes? Yes (4 is divisible by 2). So, we don't do anything. Right now list_primes=[2,3]

  4. We go to the next number, 5. Is 5 divisible by any of the numbers in list_primes? No! We append 5 to list_primes. Right now, list_primes=[2,3,5]

  5. We go to the next number, 6. Is 6 divisible by any of the numbers in list_primes? Yes (6 is divisible by 2 and also divisible by 3). So, we don't do anything. Right now list_primes=[2,3,5]

  6. And so on...









share|improve this question























  • FWIW, I'd remove the calculation of sqrt(num) from the loop condition. It's expensive to calculate and it does not change, so compute it once only. Maybe it can get optimized out automatically, but I would not count on it.
    – dave
    Nov 10 at 16:37










  • Yeah, makes sense. Thanks
    – Prabhat Soni
    11 hours ago














up vote
0
down vote

favorite












Input: A number, max (a large number)
Output: All the primes from 1 to max
Output is in the form of a list and will be [2,3,5,7,11,13,.......]
The code attempts to perform this task in an efficient way (least time complexity).



from math import sqrt 
max = (10**6)*3
print("nThis code prints all primes till: " , max , "n")
list_primes=[2]

def am_i_prime(num):
"""
Input/Parameter the function takes: An integer number
Output: returns True, if the number is prime and False if not
"""
decision=True
i=0
while(list_primes[i] <= sqrt(num)): #Till sqrt(n) to save comparisons
if(num%list_primes[i]==0):
decision=False
break
#break is inserted so that we get out of comparisons faster
#Eg. for 1568, we should break from the loop as soon as we know that 1568%2==0
i+=1
return decision


for i in range(3,max,2): #starts from 3 as our list contains 2 from the beginning
if am_i_prime(i)==True:
list_primes.append(i) #if a number is found to be prime, we append it to our list of primes

print(list_primes)


How can I make this faster? Where can I improve?
What is the time complexity of this code? Which steps are inefficient?
In what ways is the Sieve of Eratosthenes more efficient than this?



Working for the first few iterations:-



  1. We have a list_primes which contains prime numbers. It initially contains only 2.

  2. We go to the next number, 3. Is 3 divisible by any of the numbers in list_primes? No! We append 3 to list_primes. Right now, list_primes=[2,3]

  3. We go to the next number 4. Is 4 divisible by any of the numbers in list_primes? Yes (4 is divisible by 2). So, we don't do anything. Right now list_primes=[2,3]

  4. We go to the next number, 5. Is 5 divisible by any of the numbers in list_primes? No! We append 5 to list_primes. Right now, list_primes=[2,3,5]

  5. We go to the next number, 6. Is 6 divisible by any of the numbers in list_primes? Yes (6 is divisible by 2 and also divisible by 3). So, we don't do anything. Right now list_primes=[2,3,5]

  6. And so on...









share|improve this question























  • FWIW, I'd remove the calculation of sqrt(num) from the loop condition. It's expensive to calculate and it does not change, so compute it once only. Maybe it can get optimized out automatically, but I would not count on it.
    – dave
    Nov 10 at 16:37










  • Yeah, makes sense. Thanks
    – Prabhat Soni
    11 hours ago












up vote
0
down vote

favorite









up vote
0
down vote

favorite











Input: A number, max (a large number)
Output: All the primes from 1 to max
Output is in the form of a list and will be [2,3,5,7,11,13,.......]
The code attempts to perform this task in an efficient way (least time complexity).



from math import sqrt 
max = (10**6)*3
print("nThis code prints all primes till: " , max , "n")
list_primes=[2]

def am_i_prime(num):
"""
Input/Parameter the function takes: An integer number
Output: returns True, if the number is prime and False if not
"""
decision=True
i=0
while(list_primes[i] <= sqrt(num)): #Till sqrt(n) to save comparisons
if(num%list_primes[i]==0):
decision=False
break
#break is inserted so that we get out of comparisons faster
#Eg. for 1568, we should break from the loop as soon as we know that 1568%2==0
i+=1
return decision


for i in range(3,max,2): #starts from 3 as our list contains 2 from the beginning
if am_i_prime(i)==True:
list_primes.append(i) #if a number is found to be prime, we append it to our list of primes

print(list_primes)


How can I make this faster? Where can I improve?
What is the time complexity of this code? Which steps are inefficient?
In what ways is the Sieve of Eratosthenes more efficient than this?



Working for the first few iterations:-



  1. We have a list_primes which contains prime numbers. It initially contains only 2.

  2. We go to the next number, 3. Is 3 divisible by any of the numbers in list_primes? No! We append 3 to list_primes. Right now, list_primes=[2,3]

  3. We go to the next number 4. Is 4 divisible by any of the numbers in list_primes? Yes (4 is divisible by 2). So, we don't do anything. Right now list_primes=[2,3]

  4. We go to the next number, 5. Is 5 divisible by any of the numbers in list_primes? No! We append 5 to list_primes. Right now, list_primes=[2,3,5]

  5. We go to the next number, 6. Is 6 divisible by any of the numbers in list_primes? Yes (6 is divisible by 2 and also divisible by 3). So, we don't do anything. Right now list_primes=[2,3,5]

  6. And so on...









share|improve this question















Input: A number, max (a large number)
Output: All the primes from 1 to max
Output is in the form of a list and will be [2,3,5,7,11,13,.......]
The code attempts to perform this task in an efficient way (least time complexity).



from math import sqrt 
max = (10**6)*3
print("nThis code prints all primes till: " , max , "n")
list_primes=[2]

def am_i_prime(num):
"""
Input/Parameter the function takes: An integer number
Output: returns True, if the number is prime and False if not
"""
decision=True
i=0
while(list_primes[i] <= sqrt(num)): #Till sqrt(n) to save comparisons
if(num%list_primes[i]==0):
decision=False
break
#break is inserted so that we get out of comparisons faster
#Eg. for 1568, we should break from the loop as soon as we know that 1568%2==0
i+=1
return decision


for i in range(3,max,2): #starts from 3 as our list contains 2 from the beginning
if am_i_prime(i)==True:
list_primes.append(i) #if a number is found to be prime, we append it to our list of primes

print(list_primes)


How can I make this faster? Where can I improve?
What is the time complexity of this code? Which steps are inefficient?
In what ways is the Sieve of Eratosthenes more efficient than this?



Working for the first few iterations:-



  1. We have a list_primes which contains prime numbers. It initially contains only 2.

  2. We go to the next number, 3. Is 3 divisible by any of the numbers in list_primes? No! We append 3 to list_primes. Right now, list_primes=[2,3]

  3. We go to the next number 4. Is 4 divisible by any of the numbers in list_primes? Yes (4 is divisible by 2). So, we don't do anything. Right now list_primes=[2,3]

  4. We go to the next number, 5. Is 5 divisible by any of the numbers in list_primes? No! We append 5 to list_primes. Right now, list_primes=[2,3,5]

  5. We go to the next number, 6. Is 6 divisible by any of the numbers in list_primes? Yes (6 is divisible by 2 and also divisible by 3). So, we don't do anything. Right now list_primes=[2,3,5]

  6. And so on...






algorithm time-complexity primes sieve-of-eratosthenes






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 11 hours ago

























asked Nov 10 at 13:33









Prabhat Soni

12




12











  • FWIW, I'd remove the calculation of sqrt(num) from the loop condition. It's expensive to calculate and it does not change, so compute it once only. Maybe it can get optimized out automatically, but I would not count on it.
    – dave
    Nov 10 at 16:37










  • Yeah, makes sense. Thanks
    – Prabhat Soni
    11 hours ago
















  • FWIW, I'd remove the calculation of sqrt(num) from the loop condition. It's expensive to calculate and it does not change, so compute it once only. Maybe it can get optimized out automatically, but I would not count on it.
    – dave
    Nov 10 at 16:37










  • Yeah, makes sense. Thanks
    – Prabhat Soni
    11 hours ago















FWIW, I'd remove the calculation of sqrt(num) from the loop condition. It's expensive to calculate and it does not change, so compute it once only. Maybe it can get optimized out automatically, but I would not count on it.
– dave
Nov 10 at 16:37




FWIW, I'd remove the calculation of sqrt(num) from the loop condition. It's expensive to calculate and it does not change, so compute it once only. Maybe it can get optimized out automatically, but I would not count on it.
– dave
Nov 10 at 16:37












Yeah, makes sense. Thanks
– Prabhat Soni
11 hours ago




Yeah, makes sense. Thanks
– Prabhat Soni
11 hours ago












2 Answers
2






active

oldest

votes

















up vote
0
down vote













Interestingly, it takes a rather deep mathematical theorem to prove that your algorithm is correct at all. The theorem is: "For every n ≥ 2, there is a prime number between n and n^2". I know it has been proven, and much stricter bounds are proven, but I must admit I wouldn't know how to prove it myself. And if this theorem is not correct, then the loop in am_i_prime can go past the bounds of the array.



The number of primes ≤ k is O (k / log k) - this is again a very deep mathematical theorem. Again, beyond me to prove.



But anyway, there are about n / log n primes up to n, and for these primes the loop will iterate through all primes up to n^(1/2), and there are O (n^(1/2) / log n) of them.



So for the primes alone, the runtime is therefore O (n^1.5 / log^2 n), so that is a lower bound. With some effort it should be possible to prove that for all numbers, the runtime is asymptotically the same.



O (n^1.5 / log n) is obviously an upper bound, but experimentally the number of divisions to find all primes ≤ n seems to be ≤ 2 n^1.5 / log^2 n, where log is the natural logarithm.






share|improve this answer






















  • Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
    – Prabhat Soni
    10 hours ago


















up vote
-1
down vote













O(N**2)



Approximately speaking, the first call to am_I_prime does 1 comparison, the second does 2, ..., so the total count is 1 + 2 + ... + N, which is (N * (N-1)) / 2, which has order N-squared.






share|improve this answer




















  • Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
    – gnasher729
    Nov 10 at 16:49










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239482%2fgenerating-prime-numbers-from-1-to-n-python3-how-to-improve-efficiency-and-what%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote













Interestingly, it takes a rather deep mathematical theorem to prove that your algorithm is correct at all. The theorem is: "For every n ≥ 2, there is a prime number between n and n^2". I know it has been proven, and much stricter bounds are proven, but I must admit I wouldn't know how to prove it myself. And if this theorem is not correct, then the loop in am_i_prime can go past the bounds of the array.



The number of primes ≤ k is O (k / log k) - this is again a very deep mathematical theorem. Again, beyond me to prove.



But anyway, there are about n / log n primes up to n, and for these primes the loop will iterate through all primes up to n^(1/2), and there are O (n^(1/2) / log n) of them.



So for the primes alone, the runtime is therefore O (n^1.5 / log^2 n), so that is a lower bound. With some effort it should be possible to prove that for all numbers, the runtime is asymptotically the same.



O (n^1.5 / log n) is obviously an upper bound, but experimentally the number of divisions to find all primes ≤ n seems to be ≤ 2 n^1.5 / log^2 n, where log is the natural logarithm.






share|improve this answer






















  • Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
    – Prabhat Soni
    10 hours ago















up vote
0
down vote













Interestingly, it takes a rather deep mathematical theorem to prove that your algorithm is correct at all. The theorem is: "For every n ≥ 2, there is a prime number between n and n^2". I know it has been proven, and much stricter bounds are proven, but I must admit I wouldn't know how to prove it myself. And if this theorem is not correct, then the loop in am_i_prime can go past the bounds of the array.



The number of primes ≤ k is O (k / log k) - this is again a very deep mathematical theorem. Again, beyond me to prove.



But anyway, there are about n / log n primes up to n, and for these primes the loop will iterate through all primes up to n^(1/2), and there are O (n^(1/2) / log n) of them.



So for the primes alone, the runtime is therefore O (n^1.5 / log^2 n), so that is a lower bound. With some effort it should be possible to prove that for all numbers, the runtime is asymptotically the same.



O (n^1.5 / log n) is obviously an upper bound, but experimentally the number of divisions to find all primes ≤ n seems to be ≤ 2 n^1.5 / log^2 n, where log is the natural logarithm.






share|improve this answer






















  • Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
    – Prabhat Soni
    10 hours ago













up vote
0
down vote










up vote
0
down vote









Interestingly, it takes a rather deep mathematical theorem to prove that your algorithm is correct at all. The theorem is: "For every n ≥ 2, there is a prime number between n and n^2". I know it has been proven, and much stricter bounds are proven, but I must admit I wouldn't know how to prove it myself. And if this theorem is not correct, then the loop in am_i_prime can go past the bounds of the array.



The number of primes ≤ k is O (k / log k) - this is again a very deep mathematical theorem. Again, beyond me to prove.



But anyway, there are about n / log n primes up to n, and for these primes the loop will iterate through all primes up to n^(1/2), and there are O (n^(1/2) / log n) of them.



So for the primes alone, the runtime is therefore O (n^1.5 / log^2 n), so that is a lower bound. With some effort it should be possible to prove that for all numbers, the runtime is asymptotically the same.



O (n^1.5 / log n) is obviously an upper bound, but experimentally the number of divisions to find all primes ≤ n seems to be ≤ 2 n^1.5 / log^2 n, where log is the natural logarithm.






share|improve this answer














Interestingly, it takes a rather deep mathematical theorem to prove that your algorithm is correct at all. The theorem is: "For every n ≥ 2, there is a prime number between n and n^2". I know it has been proven, and much stricter bounds are proven, but I must admit I wouldn't know how to prove it myself. And if this theorem is not correct, then the loop in am_i_prime can go past the bounds of the array.



The number of primes ≤ k is O (k / log k) - this is again a very deep mathematical theorem. Again, beyond me to prove.



But anyway, there are about n / log n primes up to n, and for these primes the loop will iterate through all primes up to n^(1/2), and there are O (n^(1/2) / log n) of them.



So for the primes alone, the runtime is therefore O (n^1.5 / log^2 n), so that is a lower bound. With some effort it should be possible to prove that for all numbers, the runtime is asymptotically the same.



O (n^1.5 / log n) is obviously an upper bound, but experimentally the number of divisions to find all primes ≤ n seems to be ≤ 2 n^1.5 / log^2 n, where log is the natural logarithm.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 10 at 17:34

























answered Nov 10 at 16:57









gnasher729

41k44675




41k44675











  • Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
    – Prabhat Soni
    10 hours ago

















  • Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
    – Prabhat Soni
    10 hours ago
















Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
– Prabhat Soni
10 hours ago





Yeah, that makes sense. Where did you get O (n^1.5 / log n) from? O (n^1.5 / log^2 n )makes sense cause n^1.5 / log^2 n = (n^1/2 * log n) * (n / log n) , which is time it takes for one prime * number of primes
– Prabhat Soni
10 hours ago













up vote
-1
down vote













O(N**2)



Approximately speaking, the first call to am_I_prime does 1 comparison, the second does 2, ..., so the total count is 1 + 2 + ... + N, which is (N * (N-1)) / 2, which has order N-squared.






share|improve this answer




















  • Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
    – gnasher729
    Nov 10 at 16:49














up vote
-1
down vote













O(N**2)



Approximately speaking, the first call to am_I_prime does 1 comparison, the second does 2, ..., so the total count is 1 + 2 + ... + N, which is (N * (N-1)) / 2, which has order N-squared.






share|improve this answer




















  • Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
    – gnasher729
    Nov 10 at 16:49












up vote
-1
down vote










up vote
-1
down vote









O(N**2)



Approximately speaking, the first call to am_I_prime does 1 comparison, the second does 2, ..., so the total count is 1 + 2 + ... + N, which is (N * (N-1)) / 2, which has order N-squared.






share|improve this answer












O(N**2)



Approximately speaking, the first call to am_I_prime does 1 comparison, the second does 2, ..., so the total count is 1 + 2 + ... + N, which is (N * (N-1)) / 2, which has order N-squared.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 10 at 16:35









dave

1032




1032











  • Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
    – gnasher729
    Nov 10 at 16:49
















  • Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
    – gnasher729
    Nov 10 at 16:49















Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
– gnasher729
Nov 10 at 16:49




Please read the code more carefully. It is obvious that it takes no more than O (N^1.5), but in reality (this requires bit of math) it takes O (N^1.5) / log^2 N.
– gnasher729
Nov 10 at 16:49

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239482%2fgenerating-prime-numbers-from-1-to-n-python3-how-to-improve-efficiency-and-what%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

27

Top Tejano songwriter Luis Silva dead of heart attack at 64

Category:Rhetoric