Skip to content

Prime numbers: Added description, removed unnecessary implementation, and improved current #5048

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 16 additions & 38 deletions maths/prime_numbers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import math
from typing import Generator

"""
Naive implementation of finding primes by checking if each number
is divisible by 2 or any odd number up to its root.

For a fast implementation see Sieve of Eratosthenes.
"""

Comment on lines +4 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to keep an explanation, but state that there are two impls, and you can compre both.


def slow_primes(max: int) -> Generator[int, None, None]:
"""
Expand All @@ -9,8 +16,8 @@ def slow_primes(max: int) -> Generator[int, None, None]:
[]
>>> list(slow_primes(-1))
[]
>>> list(slow_primes(-10))
[]
>>> list(slow_primes(2))
[2]
>>> list(slow_primes(25))
[2, 3, 5, 7, 11, 13, 17, 19, 23]
>>> list(slow_primes(11))
Expand All @@ -22,49 +29,20 @@ def slow_primes(max: int) -> Generator[int, None, None]:
"""
numbers: Generator = (i for i in range(1, (max + 1)))
for i in (n for n in numbers if n > 1):
for j in range(2, i):
if (i % j) == 0:
break
else:
yield i
Comment on lines -26 to -29
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove these brackets



def primes(max: int) -> Generator[int, None, None]:
"""
Return a list of all primes numbers up to max.
>>> list(primes(0))
[]
>>> list(primes(-1))
[]
>>> list(primes(-10))
[]
>>> list(primes(25))
[2, 3, 5, 7, 11, 13, 17, 19, 23]
>>> list(primes(11))
[2, 3, 5, 7, 11]
>>> list(primes(33))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
>>> list(primes(10000))[-1]
9973
"""
Comment on lines -35 to -49
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and keep the tests?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests dont make sense since we removed one of the functions, it just compared the two timings

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we keep this referential implementation. Please see #1984, #1519.

numbers: Generator = (i for i in range(1, (max + 1)))
for i in (n for n in numbers if n > 1):
if i % 2 == 0:
if i == 2:
yield 2
continue
# only need to check for factors up to sqrt(i)
bound = int(math.sqrt(i)) + 1
for j in range(2, bound):
if (i % j) == 0:
for j in range(3, bound, 2):
if i % j == 0:
break
else:
yield i


if __name__ == "__main__":
number = int(input("Calculate primes up to:\n>> ").strip())
for ret in primes(number):
for ret in slow_primes(number):
print(ret)

# Let's benchmark them side-by-side...
from timeit import timeit

print(timeit("slow_primes(1_000_000)", setup="from __main__ import slow_primes"))
print(timeit("primes(1_000_000)", setup="from __main__ import primes"))