Skip to content

Commit 08b54c6

Browse files
committedMar 25, 2022
Add notebook comparing classic and lazy prime number generation
1 parent 25ba452 commit 08b54c6

File tree

1 file changed

+271
-0
lines changed

1 file changed

+271
-0
lines changed
 

‎source-code/prime_time.ipynb

+271
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "fc3b2761-8665-477a-8bfc-58bdf2ac4f7a",
6+
"metadata": {},
7+
"source": [
8+
"# Requirements"
9+
]
10+
},
11+
{
12+
"cell_type": "code",
13+
"execution_count": 1,
14+
"id": "47182c93-a8f7-4772-9a9c-e58a433d02ba",
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"import itertools\n",
19+
"import math"
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"id": "4e0adefe-f566-4a81-a0df-0b5d0c7604cf",
25+
"metadata": {},
26+
"source": [
27+
"# Precomputed sieve"
28+
]
29+
},
30+
{
31+
"cell_type": "markdown",
32+
"id": "0f0a2be6-515a-4d25-a5c8-67b9dfefe69a",
33+
"metadata": {},
34+
"source": [
35+
"The sieve of Eratosthenes is computed and stored in a list. The overall implementation is a generator for convenience."
36+
]
37+
},
38+
{
39+
"cell_type": "code",
40+
"execution_count": 2,
41+
"id": "b6c3ba8e-e5c5-4a3a-b059-02fa0283776a",
42+
"metadata": {},
43+
"outputs": [],
44+
"source": [
45+
"def prime_numbers_precomputed(max_n):\n",
46+
" sieve = [True]*(max_n + 1)\n",
47+
" sieve[0], sieve[1] = False, False\n",
48+
" for n in range(2, math.isqrt(max_n) + 1):\n",
49+
" if sieve[n]:\n",
50+
" for non_prime in range(2*n, max_n + 1, n):\n",
51+
" sieve[non_prime] = False\n",
52+
" yield from (n for n, is_prime in enumerate(sieve) if is_prime)"
53+
]
54+
},
55+
{
56+
"cell_type": "markdown",
57+
"id": "3ad4ec7f-303b-4980-8405-db68f8e86339",
58+
"metadata": {},
59+
"source": [
60+
"Generate prime numbers upto 50."
61+
]
62+
},
63+
{
64+
"cell_type": "code",
65+
"execution_count": 4,
66+
"id": "a1ee6b85-5af0-4f4a-9a70-e1f08d177349",
67+
"metadata": {},
68+
"outputs": [
69+
{
70+
"name": "stdout",
71+
"output_type": "stream",
72+
"text": [
73+
"2\n",
74+
"3\n",
75+
"5\n",
76+
"7\n",
77+
"11\n",
78+
"13\n",
79+
"17\n",
80+
"19\n",
81+
"23\n",
82+
"29\n",
83+
"31\n",
84+
"37\n",
85+
"41\n",
86+
"43\n",
87+
"47\n"
88+
]
89+
}
90+
],
91+
"source": [
92+
"for prime in prime_numbers_precomputed(50):\n",
93+
" print(prime)"
94+
]
95+
},
96+
{
97+
"cell_type": "markdown",
98+
"id": "6eef26fa-d00d-4fab-a8d7-08ffc52590bd",
99+
"metadata": {},
100+
"source": [
101+
"# Sieve using generators"
102+
]
103+
},
104+
{
105+
"cell_type": "markdown",
106+
"id": "54049286-713e-48fa-a1fb-44078942d348",
107+
"metadata": {},
108+
"source": [
109+
"Implementation using generators, entirely lazy."
110+
]
111+
},
112+
{
113+
"cell_type": "code",
114+
"execution_count": 5,
115+
"id": "ab70534d-688f-46f4-8b30-44bf1e34ab5b",
116+
"metadata": {},
117+
"outputs": [],
118+
"source": [
119+
"def prime_numbers():\n",
120+
" def prime_number_sieve(numbers):\n",
121+
" prime = next(numbers)\n",
122+
" yield prime\n",
123+
" yield from (n for n in numbers if n % prime != 0)\n",
124+
" yield 2\n",
125+
" yield from prime_number_sieve(itertools.count(3, 2))"
126+
]
127+
},
128+
{
129+
"cell_type": "markdown",
130+
"id": "b54d4fd3-4e5a-4556-9bac-85da2ceb9e19",
131+
"metadata": {},
132+
"source": [
133+
"Again, generating the prime numbers up to 50."
134+
]
135+
},
136+
{
137+
"cell_type": "code",
138+
"execution_count": 7,
139+
"id": "d67bb1fe-8e55-45b0-aace-36ab4397acb0",
140+
"metadata": {},
141+
"outputs": [
142+
{
143+
"name": "stdout",
144+
"output_type": "stream",
145+
"text": [
146+
"2\n",
147+
"3\n",
148+
"5\n",
149+
"7\n",
150+
"11\n",
151+
"13\n",
152+
"17\n",
153+
"19\n",
154+
"23\n",
155+
"25\n",
156+
"29\n",
157+
"31\n",
158+
"35\n",
159+
"37\n",
160+
"41\n",
161+
"43\n",
162+
"47\n",
163+
"49\n"
164+
]
165+
}
166+
],
167+
"source": [
168+
"for prime in prime_numbers():\n",
169+
" if prime <= 50:\n",
170+
" print(prime)\n",
171+
" else:\n",
172+
" break"
173+
]
174+
},
175+
{
176+
"cell_type": "markdown",
177+
"id": "edf1943a-31b2-4a4e-bf96-47ea2875b567",
178+
"metadata": {},
179+
"source": [
180+
"# Comparing performance"
181+
]
182+
},
183+
{
184+
"cell_type": "code",
185+
"execution_count": 10,
186+
"id": "83d6696e-b31c-4dbc-9b0c-702c9aedc4a9",
187+
"metadata": {},
188+
"outputs": [],
189+
"source": [
190+
"max_n = 1_000_000"
191+
]
192+
},
193+
{
194+
"cell_type": "code",
195+
"execution_count": 11,
196+
"id": "bbea5e94-d82a-4be9-b4f4-152a8136c608",
197+
"metadata": {},
198+
"outputs": [
199+
{
200+
"name": "stdout",
201+
"output_type": "stream",
202+
"text": [
203+
"80.4 ms ± 2.83 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
204+
]
205+
}
206+
],
207+
"source": [
208+
"%%timeit\n",
209+
"numbers = []\n",
210+
"for prime in prime_numbers_precomputed(max_n):\n",
211+
" if prime <= max_n:\n",
212+
" numbers.append(prime)\n",
213+
" else:\n",
214+
" break"
215+
]
216+
},
217+
{
218+
"cell_type": "code",
219+
"execution_count": 12,
220+
"id": "351d9f27-6d04-4d70-b8e3-451d223f64a4",
221+
"metadata": {},
222+
"outputs": [
223+
{
224+
"name": "stdout",
225+
"output_type": "stream",
226+
"text": [
227+
"46.9 ms ± 1.48 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
228+
]
229+
}
230+
],
231+
"source": [
232+
"%%timeit\n",
233+
"numbers = []\n",
234+
"for prime in prime_numbers():\n",
235+
" if prime <= max_n:\n",
236+
" numbers.append(prime)\n",
237+
" else:\n",
238+
" break"
239+
]
240+
},
241+
{
242+
"cell_type": "markdown",
243+
"id": "1111d621-2f13-456c-ba62-a493df7fdc64",
244+
"metadata": {},
245+
"source": [
246+
"Interestingly, the lazy implementation is faster by a substantial factor, perhaps this could be improved by using a different data representation for the precomputed sieve."
247+
]
248+
}
249+
],
250+
"metadata": {
251+
"kernelspec": {
252+
"display_name": "Python 3 (ipykernel)",
253+
"language": "python",
254+
"name": "python3"
255+
},
256+
"language_info": {
257+
"codemirror_mode": {
258+
"name": "ipython",
259+
"version": 3
260+
},
261+
"file_extension": ".py",
262+
"mimetype": "text/x-python",
263+
"name": "python",
264+
"nbconvert_exporter": "python",
265+
"pygments_lexer": "ipython3",
266+
"version": "3.9.7"
267+
}
268+
},
269+
"nbformat": 4,
270+
"nbformat_minor": 5
271+
}

0 commit comments

Comments
 (0)
Please sign in to comment.