Skip to content

Commit 9aac149

Browse files
committed
First Steps into Heron's Method
1 parent bd3b026 commit 9aac149

File tree

6 files changed

+155
-4
lines changed

6 files changed

+155
-4
lines changed

bibliography/bibliography.bib

+69
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ @string { a_filaseta_michael
9292
@string { a_flannery_brian_p = "Brian P.\ Flannery" }
9393
@string { a_flight_robert_m = "Robert M.\ Flight" }
9494
@string { a_fox_emily_b = "Emily B.\ Fox" }
95+
@string { a_fowler_david = "David Fowler" }
9596
@string { a_fufezan_christian = "Christian Fufezan" }
9697
@string { a_garcia_alessandro = "Alessandro Garcia" }
9798
@string { a_garnett_roman = "Roman Garnett" }
@@ -142,6 +143,7 @@ @string { a_knuth_donald_ervin
142143
@string { a_kohn_tobias = "Tobias Kohn" }
143144
@string { a_konovalov_alexander = "Alexander Konovalov" }
144145
@string { a_korth_henry_f = "Henry F.\ Korth" }
146+
@string { a_kosheleva_olga = "Olga Kosheleva" }
145147
@string { a_krueger_richard = "Richard Krueger" }
146148
@string { a_kudlur_manjunath = "Manjunath Kudlur" }
147149
@string { a_landau_charles = "Charles Landau" }
@@ -216,6 +218,7 @@ @string { a_ribeiro_antonio_h
216218
@string { a_riesel_hans = "Hans Riesel" }
217219
@string { a_rivest_ronald_linn = "Ronald Linn Rivest" }
218220
@string { a_robertson_edmund_f = "Edmund F.\ Robertson" }
221+
@string { a_robson_eleanor = "Eleanor Robson" }
219222
@string { a_rodriguez_emily = "Emily Rodriguez" }
220223
@string { a_roscoe_timothy = "Timothy Roscoe" }
221224
@string { a_rosenblatt_bill = "Bill Rosenblatt" }
@@ -227,6 +230,7 @@ @string { a_sagher_yoram
227230
@string { a_salakoski_tapio = "Tapio Salakoski" }
228231
@string { a_salvaneschi_guido = "Guido Salvaneschi" }
229232
@string { a_scipy_1 = "{{SciPy~1.0 Contributors}}" }
233+
@string { a_scott_larkin_rigdway = "Larkin Ridgway Scott" }
230234
@string { a_setia_veenu = "Veenu Setia" }
231235
@string { a_shalev_shwartz_shai = "Shai Shalev{-}Shwartz" }
232236
@string { a_shen_kangshen = "Shen Kangshen" }
@@ -310,6 +314,7 @@ @string { l_germany_leipzig
310314
@string { l_germany_wadern = "{{Wadern}, {Saarland}, {Germany}}" }
311315
@string { l_iceland_reykjavik = "{{Reykjav{\'i}k}, {Iceland}}" }
312316
@string { l_india_noida = "{{Noida}, {Uttar Pradesh}, {India}}" }
317+
@string { l_netherlands_amsterdam = "{{Amsterdam}, {The~Netherlands}}" }
313318
@string { l_portugal_lisbon = "{{Lisbon}, {Portugal}}" }
314319
@string { l_russia_petropolis = "{{Petropolis} {(St.~Petersburg)}, {Russia}}" }
315320
@string { l_spain_leioa = "{{Leioa}, {Bizkaia}, {Spain}}" }
@@ -330,12 +335,14 @@ @string { l_usa_catonsville
330335
@string { l_usa_cambridge = "{{Cambridge}, {MA}, {USA}}" }
331336
@string { l_usa_centennial = "{{Centennial}, {CO}, {USA}}" }
332337
@string { l_usa_champaign = "{{Champaign}, {IL}, {USA}}" }
338+
@string { l_usa_cincinnati = "{{Cincinnati}, {OH}, {USA}}" }
333339
@string { l_usa_columbia = "{{Columbia}, {SC}, {USA}}" }
334340
@string { l_usa_hoboken = "{{Hoboken}, {NJ}, {USA}}" }
335341
@string { l_usa_ithaca = "{{Ithaca}, {NY}, {USA}}" }
336342
@string { l_usa_lake_buena_vista = "{{Lake Buena Vista}, {FL}, {USA}}" }
337343
@string { l_usa_new_york = "{{New York}, {NY}, {USA}}" }
338344
@string { l_usa_piscataway = "{{Piscataway}, {NJ}, {USA}}" }
345+
@string { l_usa_princeton = "{{Princeton}, {NJ}, {USA}}" }
339346
@string { l_usa_providence = "{{Providence}, {RI}, {USA}}" }
340347
@string { l_usa_reading = "{{Reading}, {MA}, {USA}}" }
341348
@string { l_usa_redwood_city = "{{Redwood City}, {CA}, {USA}}" }
@@ -368,6 +375,7 @@ @string { p_cambridge_uni_press_ass
368375
@string { p_cnri = "{Corporation for National Research Initiatives~({CNRI})}" }
369376
@string { p_crc_press = "{{CRC} Press}" }
370377
@string { p_cornell_university_library = "{Cornell Universiy Library}" }
378+
@string { p_elsevier = "{Elsevier~B.V.}" }
371379
@string { p_geeksforgeeks = "{GeeksforGeeks -- Sanchhaya Education Private Limited}" }
372380
@string { p_github = "{{GitHub} Inc}" }
373381
@string { p_iec = "{International Electrotechnical Commission~{(IEC)}}" }
@@ -388,6 +396,7 @@ @string { p_packt
388396
@string { p_pearson_education = "Pearson Education, Inc." }
389397
@string { p_microsoft_press = "{Microsoft Press}, " # p_pearson_education }
390398
@string { p_plos = "Public Library of Science~{(PLOS)}" }
399+
@string { p_princeton_university_press = "Princeton University Press" }
391400
@string { p_python_morsels = "{Python Morsels}" }
392401
@string { p_python_software_foundation = "{\python\ Software Foundation~{(PSF)}}" }
393402
@string { p_springer = "{Springer}" }
@@ -425,6 +434,7 @@ @string { pa_cambridge_uni_press_ass
425434
@string { pa_cnri = l_usa_reston }
426435
@string { pa_cornell_university_library = l_usa_ithaca }
427436
@string { pa_crc_press = l_usa_boca_raton }
437+
@string { pa_elsevier = l_netherlands_amsterdam }
428438
@string { pa_geeksforgeeks = l_india_noida}
429439
@string { pa_github = l_usa_san_francisco }
430440
@string { pa_iso_iec = l_switzerland_geneva }
@@ -445,6 +455,7 @@ @string { pa_packt
445455
@string { pa_pearson_education = l_usa_hoboken }
446456
@string { pa_microsoft_press = pa_pearson_education }
447457
@string { pa_plos = l_usa_san_francisco }
458+
@string { pa_princeton_university_press = l_usa_princeton }
448459
@string { pa_python_morsels = l_iceland_reykjavik }
449460
@string { pa_python_software_foundation = l_usa_beaverton }
450461
@string { pa_springer_cham = l_switzerland_cham }
@@ -506,6 +517,13 @@ @xdata{j_csae
506517
address = pa_ieee
507518
}
508519

520+
@xdata{j_hm,
521+
journal = {Historia Mathematica},
522+
issn = {0315-0860},
523+
publisher = p_elsevier,
524+
address = pa_elsevier
525+
}
526+
509527
@xdata{j_ijoc,
510528
journal = {{INFORMS} Journal on Computing},
511529
issn = {1091-9856},
@@ -1000,6 +1018,20 @@ @inbook{F2011TTOEAP
10001018
urldate = {2024-07-05},
10011019
}
10021020

1021+
@article{FR1998SRAIOBMY7IC,
1022+
author = a_fowler_david # and # a_robson_eleanor,
1023+
title = {Square Root Approximations in Old Babylonian Mathematics:~{YBC~7289} in Context},
1024+
xdata = {j_hm},
1025+
volume = {25},
1026+
number = {4},
1027+
date = {1998-11},
1028+
pages = {366--378},
1029+
doi = {10.1006/hmat.1998.2209},
1030+
url = {https://www.ux1.eiu.edu/~cfcid/Classes/4900/Class%20Notes/Babylonian%20Approximations.pdf},
1031+
urldate = {2024-09-25},
1032+
addendum = {Article~NO.~{HM982209}}
1033+
}
1034+
10031035
@book{G2019DSFSFPWP,
10041036
author = a_grus_joel,
10051037
title = {Data Science from Scratch: First Principles with \python},
@@ -1161,6 +1193,15 @@ @book{K1998SAS
11611193
isbn = {978-0-201-89685-5},
11621194
}
11631195

1196+
@inproceedings{K2009BMOCTSRJBOFTAOCC,
1197+
author = a_kosheleva_olga,
1198+
title = {Babylonian Method of Computing the Square Root: {J}ustifications based on Fuzzy Techniques and on Computational Complexity},
1199+
crossref = {PROC2009NAFIPS},
1200+
doi = {10.1109/NAFIPS.2009.5156463},
1201+
url = {https://www.cs.utep.edu/vladik/2009/olg09-05a.pdf},
1202+
urldate = {2024-09-25},
1203+
}
1204+
11641205
@article{KCVM2022AESOTRDIPP,
11651206
author = a_khan_faizan # and # a_chen_boqi # and # a_varro_daniel # and # a_mcintosh_shane,
11661207
title = {An Empirical Study of Type-Related Defects in \python\ Projects},
@@ -1403,6 +1444,15 @@ @proceedings{PROC2006ACE
14031444
address = pa_acm,
14041445
}
14051446

1447+
@proceedings{PROC2009NAFIPS,
1448+
title = {2009~Annual Meeting of the North American Fuzzy Information Processing Society~{(NAFIPS'09)}, } # jun # {~14-19, 2009, } # l_usa_cincinnati,
1449+
publisher = p_ieee,
1450+
address = pa_ieee,
1451+
doi = {10.1109/NAFIPS15046.2009},
1452+
date = {2009},
1453+
isbn = {978-1-4244-4575-2},
1454+
}
1455+
14061456
@proceedings{PROC2016OSDI,
14071457
title = {12th {USENIX} Symposium on Operating Systems Design and Implementation~({OSDI'16}), } # nov # {~2-4, 2016, } # l_usa_savannah,
14081458
editor = a_keeton_kimberly # and # a_roscoe_timothy,
@@ -1664,6 +1714,25 @@ @article{S1998LHATFGAOCM
16641714
doi = {10.2307/2691200},
16651715
}
16661716

1717+
@book{S2011NA,
1718+
author = a_scott_larkin_rigdway,
1719+
title = {Numerical Analysis},
1720+
date = {2011-04-18},
1721+
publisher = p_princeton_university_press,
1722+
address = pa_princeton_university_press,
1723+
doi = {10.1515/9781400838967},
1724+
isbn = {9781400838967},
1725+
}
1726+
1727+
@inbook{S2011NA2,
1728+
crossref = {S2011NA},
1729+
chapter = {1},
1730+
title = {Numerical Algorithms},
1731+
doi = {10.1515/9781400838967-002},
1732+
url = {https://assets.press.princeton.edu/chapters/s9487.pdf},
1733+
urldate = {2024-09-25}
1734+
}
1735+
16671736
@book{S2023LG,
16681737
author = a_skoulikari_anna,
16691738
title = {Learning \git},

styles/listing.sty

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ literate=%
6464
{Ψ}{{$\Psi$}}1 {Ω}{{$\Omega$}}1%
6565
{∖}{{$\setminus$}}1 {∪}{{$\cup$}}1 {∩}{{$\cap$}}1%
6666
{≈}{{$\approx$}}1 {∈}{{$\in$}}1 {∉}{{$\notin$}}1%
67+
{√}{{\raisebox{0.55ex}{$\sqrt{\relax}$}}}1%
6768
}%
6869
%
6970
\lstdefinestyle{python_style}{%

text/main/basics/simpleDataTypesAndOperations/int/int.tex

+2-2
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@
140140

141141
Finally, we can also shift bit strings to the left or right by $i$~places.
142142
The former corresponds to multiplying with~$2^i$, the latter is the same as an integer division by~$2^i$.
143-
Shifting \pythonil{22} by one bit position to the \emph{left} -- which is done by entering \pythonil{22 << 1}\pythonIdx{<<} -- therefore results in~\pythonil{44}.
143+
Shifting \pythonil{22} by one bit position to the \emph{left} -- which is done by entering \pythonil{22 << 1}\pythonIdx{<\strut<} -- therefore results in~\pythonil{44}.
144144
We already know that \pythonil{bin(22)} is \pythonil{'0b10110'} and so it comes at no surprise that \pythonil{bin(44)} is \pythonil{'0b101100'} (notice the additional \pythonil{0} that appeared on the right hand side).
145-
Shifting \pythonil{22} by two bit positions to the \emph{right} -- which is done by entering \pythonil{22 >> 2}\pythonIdx{>>} -- results in \pythonil{5}.
145+
Shifting \pythonil{22} by two bit positions to the \emph{right} -- which is done by entering \pythonil{22 >> 2}\pythonIdx{>\strut>} -- results in \pythonil{5}.
146146
The \pythonil{10} on the right hand side of the binary representation disappeared, as \pythonil{bin(5)} is \pythonil{'0b101'}.
147147

148148
Besides the binary representation of integer numbers, which is to the basis~2, there also exists the hexadecimal representation (base~16) and the octal representation (base~7).

text/main/controlFlow/conditionals/conditionals.tex

+12-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,18 @@
262262
Both programs are equivalent, but the second one only has~13 instead of 22~lines of code.
263263
Notice again how a \pgls{linter} can help us to refine and compactify our code.%
264264
%
265-
\FloatBarrier%
266265
\endhsection%
266+
%
267+
\hsection{Summary}%
268+
With the statements we discussed in this section, you are now able to create a program that makes decisions based on data.
269+
Before this, we could only perform straightforward computations and calculate the results of simple functions.
270+
Now our variables can receive the result of a function~$A$ if the input meets a condition~$B$ and otherwise the result of a function~$C$.
271+
This is already quite nice.
272+
For example, we can now implement and hard-code decision trees~\cite{RN2022AIAMA,SSBD2014UMLFTTA} and \cref{lst:conditionals:if_elif} is basically an example for that.
273+
Still, the instructions in our programs are still executed in the sequence in which we wrote them down.
274+
While our control flow can now branch, it cannot perform anything more fancy and advanced {\dots} like looping back upon itself\dots%
275+
\endhsection%
276+
%
277+
\FloatBarrier%
267278
\endhsection%
268279
%

text/main/controlFlow/controlFlow.tex

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
Our programs have no way to adapt their behavior based on their input data.
77
They cannot do one thing if a variable has a certain value and do something else otherwise.
88
They do not branch or loop.
9-
Now you will learn how to write programs that \emph{do} branch or loop.%
9+
Now we will learn how to write programs that \emph{do} branch or loop.
10+
We will learn statements that change the \emph{control flow}.%
11+
%
12+
\begin{definition}[Control Flow]%
13+
The \emph{control flow} is the order in which the statements in a program are executed.%
14+
\end{definition}%
1015
%
1116
\hinput{conditionals}{conditionals.tex}%
1217
\hinput{loops}{loops.tex}%

text/main/controlFlow/loops/loops.tex

+65
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,71 @@
346346
Maybe their future versions will.
347347
Regardless, it becomes clear that using more static analysis tools is always a good idea, as stated back in \cref{bp:manyCodeAnalysisTools}.%
348348
%
349+
\FloatBarrier%
350+
\endhsection%
351+
%
352+
\hsection{The \texttt{while} Loop}%
353+
%
354+
Old clay tablets show that the Babylonians were able to approximate~$\sqrt{2}$ maybe as far back as 4000~years ago~\cite{FR1998SRAIOBMY7IC,S2011NA2}.
355+
The mathematician Hero(n) of Alexandria, who lived in the first century~CE, specified an abstract algorithm for computing the square root of numbers which, today, is known as Heron's Method~\cite{S2011NA2,K2009BMOCTSRJBOFTAOCC}.
356+
357+
Given a number~$a$ and aiming to find the square root~$\sqrt{a}$ of~$a$, this algorithm starts with a guess~$x_0$, let's say~$x_0=1$.
358+
In each iteration~$i$, it will compute a new guess as follows~\cite{S2011NA2,K2009BMOCTSRJBOFTAOCC}:%
359+
%
360+
\begin{equation}%
361+
x_{i+1}=\frac{1}{2}\left(x_i+\frac{a}{x_i}\right)%
362+
\label{eq:heronGuessUpdate}%
363+
\end{equation}%
364+
%
365+
We can roughly imagine that the algorithm works as follows:
366+
If $x_i$ was too big~($x_i>\sqrt{a}$), then~$\frac{a}{x_i}<\sqrt{a}<x_i$.
367+
If $x_i$ was too small~($x_i<\sqrt{a}$), then $\frac{a}{x_i}>\sqrt{a}>x_i$.
368+
By computing the average of~$x_i$ and~$\frac{a}{x_i}$ as the next guess, we will approach~$\sqrt{a}$.
369+
If $x_i=\sqrt{a}$, then $\frac{a}{x_i}=\sqrt{a}$ by definition and~$x_{i+1}=x_i$.
370+
371+
If we want to implement this algorithm, we will naturally need a loop of some sort.
372+
Clearly, we perform the same computation again and again.
373+
However, a \pythonil{for}~loop will not do:
374+
We do not know the number of steps we need in advance.
375+
Of course, we could try to pick a very very huge number and then \pythonil{break} the loop when the guesses converg {\dots} but that is just ugly.
376+
The \pythonilIdx{while} comes to rescue:%
377+
%
378+
\begin{pythonSyntax}
379+
while booleanExpression:
380+
loop body statement 1
381+
loop body statement 2
382+
# ...
383+
384+
normal statement 1
385+
normal statement 2
386+
# ...
387+
\end{pythonSyntax}
388+
\FloatBarrier%
389+
%
390+
\gitPythonAndOutput{\programmingWithPythonCodeRepo}{04_loops}{while_loop_sqrt.py}{--args format}{loops:while_loop_sqrt}{%
391+
We compute the square root of a number using Heron's Method~\cite{S2011NA2,K2009BMOCTSRJBOFTAOCC} implemented as py \pythonilIdx{while} loop.}%
392+
%
393+
In the \pythonilIdx{while} loop, the body is executed as long as a Boolean expression in the head of the loop evaluates to~\pythonilIdx{True}.
394+
We now use this new construct to implement Heron's Method in \cref{lst:loops:while_loop_sqrt} and use it to compute the square roots of~0.5, 2, and~3.
395+
396+
We begin the program with an outer \pythonil{for} loop that iterates a variable~\pythonil{number} over the \pythonil{float} values \pythonil{0.5}, \pythonil{2.0}, and~\pythonil{3.0}.
397+
We want to apply the algorithm to each of these values.
398+
We use two variables~\pythonil{guess} be the current guess of what $\sqrt{\pythonil{number}}$ could be and \pythonil{old_guess} be the previous guess.%
399+
%
400+
\begin{sloppypar}%
401+
We initialize \pythonil{guess} with \pythonil{1.0}.
402+
Our \pythonilIdx{while} loop should keep iterating as long as \pythonil{guess != old_guess}.
403+
This only works because the \pythonil{float} datatype has limited precision which we will eventually exhaust, see \cref{sec:howFloatingPointNumbersWork}.
404+
Anyway, the loop condition necessitates us to store some value different from~\pythonil{1.0} in \pythonil{old_guess} initially (and we pick~\pythonil{0.0}).
405+
In the loop, first the current guess becomes the old guess via \pythonil{old_guess = guess}.
406+
Then we update the guess as in \cref{eq:heronGuessUpdate}, by setting \pythonil{guess = 0.5 * (guess + number / guess)}.%
407+
\end{sloppypar}%
408+
%
409+
Finally, we print the result of the computation, and for the sake of comparison, we also print the output of the \pythonilIdx{sqrt} function of the \pythonilIdx{math} module.
410+
As you can see, our algorithm delivers exactly the same result.
411+
Also, notice how we used the Unicode escape method from \cref{sec:unicodeChars} to represent the characters~$\sqrt{\cdot}$ and~$\approx$ as \textil{\\u221A} and \textil{\\u2248} to get them printed on the console.%
412+
%
413+
\FloatBarrier%
349414
\endhsection%
350415
%
351416
\endhsection%

0 commit comments

Comments
 (0)