emacs.d/clones/lisp/htdp.org/2022-8-7/Book/i4-5.html

246 lines
89 KiB
HTML
Raw Normal View History

2022-08-15 11:06:56 +02:00
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>Intermezzo 4: The Nature of Numbers</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="shared.css" title="default"/><link rel="stylesheet" type="text/css" href="figure.css" title="default"/><link rel="stylesheet" type="text/css" href="racket.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-racket.css" title="default"/><script type="text/javascript" src="scribble-common.js"></script><script type="text/javascript" src="figure.js"></script><script type="text/javascript" src="manual-racket.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="scribble-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_0&quot;);">&#9660;</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">How to Design Programs, Second Edition</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right"></td><td><a href="part_preface.html" class="tocviewlink" data-pltdoc="x">Preface</a></td></tr><tr><td align="right"></td><td><a href="part_prologue.html" class="tocviewlink" data-pltdoc="x">Prologue:<span class="mywbr"> &nbsp;</span> How to Program</a></td></tr><tr><td align="right">I&nbsp;</td><td><a href="part_one.html" class="tocviewlink" data-pltdoc="x">Fixed-<wbr></wbr>Size Data</a></td></tr><tr><td align="right"></td><td><a href="i1-2.html" class="tocviewlink" data-pltdoc="x">Intermezzo 1: Beginning Student Language</a></td></tr><tr><td align="right">II&nbsp;</td><td><a href="part_two.html" class="tocviewlink" data-pltdoc="x">Arbitrarily Large Data</a></td></tr><tr><td align="right"></td><td><a href="i2-3.html" class="tocviewlink" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a></td></tr><tr><td align="right">III&nbsp;</td><td><a href="part_three.html" class="tocviewlink" data-pltdoc="x">Abstraction</a></td></tr><tr><td align="right"></td><td><a href="i3-4.html" class="tocviewlink" data-pltdoc="x">Intermezzo 3: Scope and Abstraction</a></td></tr><tr><td align="right">IV&nbsp;</td><td><a href="part_four.html" class="tocviewlink" data-pltdoc="x">Intertwined Data</a></td></tr><tr><td align="right"></td><td><a href="i4-5.html" class="tocviewselflink" data-pltdoc="x">Intermezzo 4: The Nature of Numbers</a></td></tr><tr><td align="right">V&nbsp;</td><td><a href="part_five.html" class="tocviewlink" data-pltdoc="x">Generative Recursion</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html" class="tocviewlink" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a></td></tr><tr><td align="right">VI&nbsp;</td><td><a href="part_six.html" class="tocviewlink" data-pltdoc="x">Accumulators</a></td></tr><tr><td align="right"></td><td><a href="part_epilogue.html" class="tocviewlink" data-pltdoc="x">Epilogue:<span class="mywbr"> &nbsp;</span> Moving On</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_1&quot;);">&#9658;</a></td><td></td><td><a href="i4-5.html" class="tocviewselflink" data-pltdoc="x">Intermezzo 4: The Nature of Numbers</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right"></td><td><a href="i4-5.html#%28part._.Fixed-.Size_.Number_.Arithmetic%29" class="tocviewlink" data-pltdoc="x">F
underlying hardware and true mathematics. The typical computer hardware
represents numbers with fixed-size chunks of data;<span class="refelem"><span class="refcolumn"><span class="refcontent">These
chunks are called <span style="font-style: italic">bits</span>, <span style="font-style: italic">bytes</span>, and <span style="font-style: italic">words</span>.</span></span></span>
they also come with processors that work on just such chunks. In
paper-and-pencil calculations, we don&rsquo;t worry about how many digits we
process; in principle, we can deal with numbers that consist of one digit,
10 digits, or 10,000 digits. Thus, if a programming language uses the
numbers from the underlying hardware, its calculations are as efficient as
possible. If it sticks to the numbers we know from mathematics, it must
translate those into chunks of hardware data and back&#8212;<wbr></wbr>and these
translations cost time. Because of this cost, most creators of programming
languages adopt the hardware-based choice.</p><p>This intermezzo explains the hardware representation of numbers as an
exercise in data representation. Concretely, the first subsection
introduces a concrete fixed-size data representation for numbers, discusses
how to map numbers into this representation, and hints at how calculations
work on such numbers. The second and third sections illustrate the two most
fundamental problems of this choice: arithmetic overflow and underflow,
respectively. The last one sketches how arithmetic in the teaching
languages works; its number system <span style="font-weight: bold">generalizes</span> what you find in most
of today&rsquo;s programming languages. The final exercises show how bad things
can get when programs compute with numbers.</p><h3><a name="(part._.Fixed-.Size_.Number_.Arithmetic)"></a>Fixed-Size Number Arithmetic</h3><p>Suppose we can use four digits to represent numbers. If we represent
natural numbers, one representable range is <span style="font-style: italic"></span>[<span style="font-style: italic"></span>0<span style="font-style: italic">,</span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>)<span style="font-style: italic"></span>. For real
numbers, we could pick 10,000 fractions between <span style="font-style: italic"></span>0<span style="font-style: italic"></span> and <span style="font-style: italic"></span>1<span style="font-style: italic"></span> or
5,000 between <span style="font-style: italic"></span>0<span style="font-style: italic"></span> and <span style="font-style: italic"></span>1<span style="font-style: italic"></span> and another 5,000 between <span style="font-style: italic"></span>1<span style="font-style: italic"></span> and
<span style="font-style: italic"></span>2<span style="font-style: italic"></span>, and so on. In either case, four digits can represent at most
10,000 numbers for some chosen interval, while the number line for this
interval contains an infinite number of numbers.</p><p><div class="SIntrapara">The common choice for hardware numbers is to use so-called scientific
notation, meaning numbers are represented with two parts:<span class="refelem"><span class="refcolumn"><span class="refcontent">For
pure scientific notation, the base is between 0 and 9; we ignore this constraint.</span></span></span>
</div><div class="SIntrapara"><ol><li><p>a <span style="font-style: italic">mantissa</span>, which is a base number, and</p></li><li><p>an <span style="font-style: italic">exponent</span>, which is used to determine a 10-based factor.</p></li></ol></div><div class="SIntrapara">Expressed as a formula, we write numbers as
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_154.png" alt="image" width="37" height="8"/></p></blockquote></div><div class="SIntrapara">where <span style="font-style: italic">m</span> is the mantissa and <span style="font-style: italic">e</span> the exponent. For example, one
representation of <span style="font-style: italic"></span>1<span style="font-style: italic"></span>2<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> with this scheme is
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_155.png" alt="image" width="48" height="13"/></p></blockquote></div><div class="SIntrapara">another one is </div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_156.png" alt="image" width="41" height="10"/></p></blockquote></div><div class="SIntrapara">In general, a number has several equivalents in this representation.</div></p><p><div class="SIntrapara">We can also use negative exponents, which add fractions at the cost of one
extra piece of data: the sign of the exponent. For example,
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_157.png" alt="image" width="39" height="10"/></p></blockquote></div><div class="SIntrapara">stands for
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_158.png" alt="image" width="22" height="15"/></p></blockquote></div></p><p><div class="SIntrapara">To use a form of mantissa-exponent notation for our problem, we must decide
how many of the four digits we wish to use for the representation of the mantissa and
how many for the exponent. Here we use two for each plus a sign for the
exponent; other choices are possible. Given this decision, we can still
represent 0 as
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_159.png" alt="image" width="38" height="10"/></p></blockquote></div><div class="SIntrapara">The maximal number we can represent is
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_160.png" alt="image" width="50" height="13"/></p></blockquote></div><div class="SIntrapara">which is 99 followed by 99 0&rsquo;s. Using the negative exponents, we can add
fractions all the way down to
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_161.png" alt="image" width="57" height="13"/></p></blockquote></div><div class="SIntrapara">which is the smallest representable number. In sum, using scientific
notation with four digits (and a sign), we can represent a vast range of
numbers and fractions, but this improvement comes with its own problems.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._587))"></a>
<a name="(idx._(gentag._588))"></a>
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -&gt; </span><a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">makes an instance of </span><a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a><span class="RktCmt"> after checking the arguments</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktSym">m</span><span class="hspace">&nbsp;</span><span class="RktSym">s</span><span class="hspace">&nbsp;</span><span class="RktSym">e</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x">&lt;=</a></span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="hspace">&nbsp;</span><span class="RktSym">m</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x">&lt;=</a></span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="hspace">&nbsp;</span><span class="RktSym">e</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace">&nbsp;</span><span class="RktSym">s</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://do
a data representation in ISL+ and by running some experiments. Let&rsquo;s
represent a fixed-size number with a structure that has three fields:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace">&nbsp;</span><span class="RktSym">inex</span><span class="hspace">&nbsp;</span><span class="RktPn">[</span><span class="RktSym">mantissa</span><span class="hspace">&nbsp;</span><span class="RktSym">sign</span><span class="hspace">&nbsp;</span><span class="RktSym">exponent</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">An </span><a name="(tech._inex)"></a><span style="font-style: italic">Inex</span><span class="RktCmt"> is a structure: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">make-inex</span><span class="stt"> </span><a href="i4-5.html#%28tech._n99%29" class="techoutside" data-pltdoc="x"><span class="techinside">N99</span></a><span class="stt"> </span><a href="i4-5.html#%28tech._%29" class="techoutside" data-pltdoc="x"><span class="techinside">S</span></a><span class="stt"> </span><a href="i4-5.html#%28tech._n99%29" class="techoutside" data-pltdoc="x"><span class="techinside">N99</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">An </span><a name="(tech._)"></a><span style="font-style: italic">S</span><span class="RktCmt"> is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">&ndash;</span><span class="RktCmt"> </span><span class="RktVal">1</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">&ndash;</span><span class="RktCmt"> </span><span class="RktVal"><span class="nobreak">-1</span></span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">An </span><a name="(tech._n99)"></a><span style="font-style: italic">N99</span><span class="RktCmt"> is an </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> between </span><span class="RktVal">0</span><span class="RktCmt"> and </span><span class="RktVal">99</span><span class="RktCmt"> (inclusive).</span></td></tr></table></blockquote></div><div class="SIntrapara">Because the conditions on the fields of an <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> are so stringent, we
define the function <span class="RktSym">create-inex</span> to instantiate this structure type
definition; see <a href="i4-5.html#%28counter._%28figure._fig~3ainexact-construct%29%29" data-pltdoc="x">figure&nbsp;<span class="FigureRef">143</span></a>. The figure also defines
<span class="RktSym">inex-&gt;number</span>, which turns <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>es into numbers using the
above formula.</div></p><p><div class="SIntrapara">Let&rsquo;s translate the above example, <span class="RktVal">1200</span>, into our data representation:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">12</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Representing <span class="RktVal">1200</span> as <img src="pict_162.png" alt="image" width="44" height="10"/> is illegal, however,
according to our <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> data definition:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">120</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">bad values given</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">For other numbers, though, we can find two <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> equivalents. One
example is <span class="RktVal">5e-19</span>:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">50</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">20</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">(make-inex 50 -1 20)</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">5</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">19</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">(make-inex 5 -1 19)</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Use <span class="RktSym">inex-&gt;number</span> to confirm the equivalence of these two numbers.</div></p><p><div class="SIntrapara">With <span class="RktSym">create-inex</span> it is also easy to delimit the range of
representable numbers, which is actually quite small for many applications:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">MAX-POSITIVE</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">MIN-POSITIVE</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The question is which of the real numbers in the range between 0 and
<span class="RktSym">MAX-POSITIVE</span> can be translated into an <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>. In particular,
any positive number less than
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_163.png" alt="image" width="29" height="10"/></p></blockquote></div><div class="SIntrapara">has no equivalent <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>. Similarly, the representation has gaps in
the middle. For example, the immediate successor of
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">12</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">is
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">13</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The first <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> represents <span style="font-style: italic"></span>1<span style="font-style: italic"></span>2<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, the second one <span style="font-style: italic"></span>1<span style="font-style: italic"></span>3<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>.
Numbers in the middle, say <span style="font-style: italic"></span>1<span style="font-style: italic"></span>2<span style="font-style: italic"></span>4<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, can be represented as one or the
other&#8212;<wbr></wbr>no other <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> makes sense. The standard choice is to round
the number to the closest representable equivalent, and that is what
computer scientists mean with <span style="font-style: italic">inexact numbers</span>. That is, the
chosen data representation forces us to map mathematical numbers to
approximations.</div></p><p><div class="SIntrapara">Finally, we must also consider arithmetic operations on <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>
structures. Adding two <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> representations with the same exponent
means adding the two mantissas:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex+</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">3</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Translated into mathematical notation, we have
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_164.png" alt="image" width="68" height="42"/></p></blockquote></div><div class="SIntrapara">When the addition of two mantissas yields too many digits, we have to use
the closest neighbor in <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>. Consider adding <img src="pict_165.png" alt="image" width="39" height="10"/>
to itself. Mathematically we get
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_166.png" alt="image" width="50" height="13"/></p></blockquote></div><div class="SIntrapara">but we can&rsquo;t just translate this number naively into our chosen
representation because <img src="pict_167.png" alt="image" width="47" height="9"/>. The proper corrective action is to
represent the result as
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_168.png" alt="image" width="44" height="10"/></p></blockquote></div><div class="SIntrapara">Or, translated into ISL+, we must ensure that <span class="RktSym">inex+</span> computes as
follows:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex+</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">55</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">55</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">11</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">More generally, if the mantissa of the result is too large, we must divide
it by <span class="RktVal">10</span> and increase the exponent by one.</div></p><p><div class="SIntrapara">Sometimes the result contains more mantissa digits than we can
represent. In those cases, <span class="RktSym">inex+</span> must round to the closest
equivalent in the <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> world. For example:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex+</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">56</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">56</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">11</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Compare this with the precise calculation:
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_169.png" alt="image" width="249" height="13"/></p></blockquote></div></p><p><div class="SIntrapara">Because the result has too many mantissa digits, the integer division of
the result mantissa by <span class="RktVal">10</span> produces an approximate result:
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_170.png" alt="image" width="44" height="10"/></p></blockquote></div><div class="SIntrapara">This is an example of the many approximations in <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>
arithmetic.<span class="refelem"><span class="refcolumn"><span class="refcontent">And <span style="font-weight: bold">inexact</span> is appropriate.</span></span></span></div></p><p><div class="SIntrapara">We can also multiply <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> numbers. Recall that
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_171.png" alt="image" width="121" height="44"/></p></blockquote></div><div class="SIntrapara">Thus we get:
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_172.png" alt="image" width="164" height="10"/></p></blockquote></div><div class="SIntrapara">or, in ISL+ notation:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex*</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">4</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">8</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">10</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">16</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">14</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As with addition, things are not straightforward. When the result
has too many significant digits in the mantissa, <span class="RktSym">inex*</span> has to
increase the exponent:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex*</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">20</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktVal">5</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">10</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">6</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">And just like <span class="RktSym">inex+</span>, <span class="RktSym">inex*</span> introduces an approximation
if the true mantissa doesn&rsquo;t have an exact equivalent in <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex*</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">27</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktVal">7</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">19</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">4</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><a name="(counter._(exercise._ex~3ainex-arith-plus))"></a><span style="font-weight: bold">Exercise</span>&nbsp;412. Design <span class="RktSym">inex+</span>. The function adds
two <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> representations of numbers that have the same exponent. The
function must be able to deal with inputs that increase the
exponent. Furthermore, it must signal its own error if the result is out of
range, not rely on <span class="RktSym">create-inex</span> for error checking.</p><p><div class="SIntrapara"><span style="font-weight: bold">Challenge</span> Extend <span class="RktSym">inex+</span> so that it can deal with inputs
whose exponents differ by <span class="RktVal">1</span>:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">inex+</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">11</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Do not attempt to deal with larger classes of inputs than that without
reading the following subsection. <a href="i4-5.html#%28counter._%28exercise._ex~3ainex-arith-plus%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3ainex-arith-times))"></a><span style="font-weight: bold">Exercise</span>&nbsp;413. Design <span class="RktSym">inex*</span>. The function
multiplies two <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> representations of numbers, including inputs
that force an additional increase of the output&rsquo;s exponent. Like
<span class="RktSym">inex+</span>, it must signal its own error if the result is out of range,
not rely on <span class="RktSym">create-inex</span> to perform error checking. <a href="i4-5.html#%28counter._%28exercise._ex~3ainex-arith-times%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3ainex-arith-round))"></a><span style="font-weight: bold">Exercise</span>&nbsp;414. As this section illustrates, gaps in the
data representation lead to round-off errors when numbers are mapped to
<a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>es. The problem is, such round-off errors accumulate across
computations.</p><p>Design <span class="RktSym">add</span>, a function that adds up <span class="RktSym">n</span> copies of
<span class="RktVal">#i1/185</span><span class="RktMeta"></span>. For your examples, use <span class="RktVal">0</span> and <span class="RktVal">1</span>; for the
latter, use a tolerance of <span class="RktVal">0.0001</span>. What is the result for
<span class="RktPn">(</span><span class="RktSym">add</span><span class="stt"> </span><span class="RktVal">185</span><span class="RktPn">)</span>? What would you expect? What happens if you multiply
the result with a large number?</p><p>Design <span class="RktSym">sub</span>. The function counts how often <span class="RktVal">1/185</span> can be
subtracted from the argument until it is <span class="RktVal">0</span>. Use <span class="RktVal">0</span> and
<span class="RktVal">1/185</span> for your examples. What are the expected results? What are
the results for <span class="RktPn">(</span><span class="RktSym">sub</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span> and <span class="RktPn">(</span><span class="RktSym">sub</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#i1.0</span><span class="RktPn">)</span><span class="RktMeta"></span>? What happens in
the second case? Why? <a href="i4-5.html#%28counter._%28exercise._ex~3ainex-arith-round%29%29" class="ex-end" data-pltdoc="x"></a></p><h3><a name="(part._.Overflow)"></a>Overflow</h3><p><div class="SIntrapara">While scientific notation expands the range of numbers we can
represent with fixed-size chunks of data, it is still finite. Some numbers
are just too big to fit into a fixed-size number representation. For example,
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_173.png" alt="image" width="49" height="10"/></p></blockquote></div><div class="SIntrapara">can&rsquo;t be represented because the exponent 500 won&rsquo;t fit into two digits,
and the mantissa is as large as legally possible.</div></p><p><div class="SIntrapara">Numbers that are too large for <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> can arise during a computation.
For example, two numbers that we can represent can add up to a number that
we cannot represent:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex+</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">50</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">50</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">100</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">which violates the data definition. When <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> arithmetic produces
numbers that are too large to be represented, we speak of (arithmetic)
<span style="font-style: italic">overflow</span>.</div></p><p>When overflow takes place, some language implementations signal an error
and stop the computation. Others designate some symbolic value, called
<span style="font-style: italic">infinity</span>, to represent such numbers and propagate it through
arithmetic operations.</p><p><span style="font-weight: bold">Note</span> If <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>es had a sign field for the mantissa, then two
negative numbers can add up to one that is so negative that it can&rsquo;t be
represented either. This is called <span style="font-style: italic">overflow in the negative
direction</span>. <span style="font-weight: bold">End</span></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aflow-large))"></a><span style="font-weight: bold">Exercise</span>&nbsp;415. ISL+ uses <span class="RktVal">+inf.0</span> to deal with
overflow. Determine the integer <span class="RktSym">n</span> such that
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#i10.0</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote></div><div class="SIntrapara">is an inexact number while <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#i10.</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">n</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span> is approximated
with <span class="RktVal">+inf.0</span>. <span style="font-weight: bold">Hint</span> Design a function to compute
<span class="RktSym">n</span>. <a href="i4-5.html#%28counter._%28exercise._ex~3aflow-large%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h3><a name="(part._.Underflow)"></a>Underflow</h3><p><div class="SIntrapara">At the opposite end of the spectrum, there are small numbers that don&rsquo;t
have a representation in <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>. For example, <img src="pict_174.png" alt="image" width="34" height="10"/> is not
0, but it&rsquo;s smaller than the smallest non-zero number we can represent. An
(arithmetic) <span style="font-style: italic">underflow</span> arises when we multiply two small numbers
and the result is too small for <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inex*</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">10</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">99</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace">&nbsp;</span><span class="RktVal">109</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">which signals an error.</div></p><p>When underflow occurs, some language implementations signal an error;
others use 0 to approximate the result. Using 0 to approximate underflow is
qualitatively different from picking an approximate representation of a
number in <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a>. Concretely, approximating <span style="font-style: italic"></span>1<span style="font-style: italic"></span>2<span style="font-style: italic"></span>5<span style="font-style: italic"></span>0<span style="font-style: italic"></span> with
<span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="stt"> </span><span class="RktVal">12</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</span> drops significant digits from the mantissa,
but the result is always within 10% of the number to be
represented. Approximating an underflow, however, means dropping the entire
mantissa, meaning the result is not within a predictable percentage range
of the true result.</p><p><a name="(counter._(exercise._ex~3aflow-small))"></a><span style="font-weight: bold">Exercise</span>&nbsp;416. ISL+ uses <span class="RktVal">#i0.0</span><span class="RktMeta"></span> to approximate
underflow. Determine the smallest integer <span class="RktSym">n</span> such that <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#i10.0</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktMeta"></span> is still an inexact ISL+ number and <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#i10.</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">n</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span> is approximated with <span class="RktVal">0</span>. <span style="font-weight: bold">Hint</span> Use a function to compute
<span class="RktSym">n</span>. Consider abstracting over this function and the solution of
<a href="i4-5.html#%28counter._%28exercise._ex~3aflow-large%29%29" data-pltdoc="x">exercise&nbsp;415</a>. <a href="i4-5.html#%28counter._%28exercise._ex~3aflow-small%29%29" class="ex-end" data-pltdoc="x"></a></p><h3><a name="(part.__.S.L_.Numbers)"></a>*SL Numbers</h3><p>Most programming languages support only approximate number
representations<span class="refelem"><span class="refcolumn"><span class="refcontent">Inexact real representations come in several
flavors: <span style="font-style: italic">float</span>, <span style="font-style: italic">double</span>, <span style="font-style: italic">extflonum</span>, and so
on.</span></span></span> and arithmetic for numbers. A typical language limits its integers to
an interval that is related to the size of the chunks of the hardware on
which it runs. Its representation of real numbers is loosely based on the
sketch in the preceding sections, though with larger chunks than the four
digits <a href="i4-5.html#%28tech._inex%29" class="techoutside" data-pltdoc="x"><span class="techinside">Inex</span></a> uses and with digits from the 2-based number system.</p><p>The teaching languages support both exact and inexact numbers. Their
integers and rationals are arbitrarily large and precise, limited only by
the absolute size of the computer&rsquo;s entire memory. For calculations on
these numbers, our teaching languages use the underlying hardware as long
as the involved rationals fit into the supported chunks of data; it
automatically switches to a different representation and to a different
version of the arithmetic operations for numbers outside of this
interval. Their real numbers come in two flavors: exact and inexact. An
exact number truly represents a real number; an inexact one approximates a
real number in the spirit of the preceding sections. Arithmetic operations
preserve exactness when possible; they produce an inexact result when
necessary. Thus, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._sqrt%29%29" class="RktValLink" data-pltdoc="x">sqrt</a></span> returns an inexact number for both the exact
and inexact representation of <span class="RktVal">2</span>. In contrast, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._sqrt%29%29" class="RktValLink" data-pltdoc="x">sqrt</a></span>
produces an exact <span class="RktVal">2</span> when given exact <span class="RktVal">4</span> and <span class="RktVal">#i2.0</span><span class="RktMeta"></span>
for an input of <span class="RktVal">#i4.0</span><span class="RktMeta"></span>. Finally, a numeric constant in a teaching
program is understood as an exact rational, unless it is prefixed with
<span class="stt">#i</span>.</p><p>Plain Racket interprets all decimal numbers as inexact numbers; it also
renders all real numbers as decimals, regardless of whether they are exact
or inexact. The implication is that all such numbers are dangerous
because they are likely to be inexact approximations of the true number. A
programmer can force Racket to interpret numbers with a dot as exact by
prefixing numerical constants with <span class="stt">#e</span>.</p><p>At this point, you may wonder how much a program&rsquo;s results may differ from
the true results if it uses these inexact numbers. This question is one
that early computer scientists struggled with a lot, and over the
past<span class="refelem"><span class="refcolumn"><span class="refcontent">For an accessible introduction&#8212;<wbr></wbr>using Racket&#8212;<wbr></wbr>read
<a href="Https://jeapostrophe.github.io/home/static/tm-cise2014.pdf"><span style="font-style: italic">Practically Accurate Floating-Point
Math</span></a>, an article on error analysis by Neil Toronto
and Jay McCarthy. It is also fun to watch
<a href="https://www.youtube.com/watch?v=HmtgHVwja4k"><span style="font-style: italic">Debugging Floating-Point Math in
Racket</span></a>, Neil Toronto&rsquo;s RacketCon 2011 lecture, available on YouTube.</span></span></span>
few decades these studies have created a separate field,
called <span style="font-style: italic">numerical analysis</span>. Every computer scientist, and indeed,
every person who uses computers and software, ought to be aware of its
existence and some of its basic insights into the workings of numeric
programs. As a first taste, the following exercises illustrate how bad
things can get. Work through them to never lose sight of the problems of
inexact numbers.</p><p><a name="(counter._(exercise._ex~3adr-number))"></a><span style="font-weight: bold">Exercise</span>&nbsp;417. Evaluate <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="stt"> </span><span class="RktVal">1.001</span><span class="stt"> </span><span class="RktVal">1e-12</span><span class="RktPn">)</span>
in Racket and in ISL+. Explain what you see. <a href="i4-5.html#%28counter._%28exercise._ex~3adr-number%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3ainex-time))"></a><span style="font-weight: bold">Exercise</span>&nbsp;418. Design <span class="RktSym">my-expt</span> without using
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span>. The function raises the first given number to the power of
the second one, a natural number. Using this function, conduct the
following experiment. Add
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">inex</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">#i1e-12</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">exac</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">1e-12</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">to the definitions area. What is <span class="RktPn">(</span><span class="RktSym">my-expt</span><span class="stt"> </span><span class="RktSym">inex</span><span class="stt"> </span><span class="RktVal">30</span><span class="RktPn">)</span>? And how about
<span class="RktPn">(</span><span class="RktSym">my-expt</span><span class="stt"> </span><span class="RktSym">exac</span><span class="stt"> </span><span class="RktVal">30</span><span class="RktPn">)</span>? Which answer is more useful? <a href="i4-5.html#%28counter._%28exercise._ex~3ainex-time%29%29" class="ex-end" data-pltdoc="x"></a></div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">JANUS</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktVal">31.0</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i2e+34</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i-1.2345678901235e+80</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">2749.0</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal"><span class="nobreak">-2</span>939234.0</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i-2e+33</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i3.2e+270</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">17.0</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i-2.4e+270</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i4.2344294738446e+170</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">1.0</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#i-8e+269</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">0.0</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">99.0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3ajanus))" x-target-lift="Figure"></a>Figure&nbsp;144: </span>A Janus-faced series of inexact numbers</span></p></blockquote><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3ajanus))"></a><span style="font-weight: bold">Exercise</span>&nbsp;419. When you add two inexact numbers of vastly different
orders of magnitude, you may get the larger one back as the result. For
example, if a number system uses only 15 significant digits, we run
into problems when adding numbers that vary by more than a factor of
<img src="pict_175.png" alt="image" width="21" height="10"/>:
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_176.png" alt="image" width="231" height="13"/></p></blockquote></div><div class="SIntrapara">but the closest representable answer is <img src="pict_177.png" alt="image" width="21" height="10"/>.</div></p><p><div class="SIntrapara">At first glance, this approximation doesn&rsquo;t look too bad. Being wrong by
one part in <img src="pict_178.png" alt="image" width="21" height="10"/> (ten million billion) is close enough to the
truth. Unfortunately, this kind of problem can add up to huge problems.
Consider the list of numbers in <a href="i4-5.html#%28counter._%28figure._fig~3ajanus%29%29" data-pltdoc="x">figure&nbsp;<span class="FigureRef">144</span></a> and determine the
values of these expressions:
</div><div class="SIntrapara"><ul><li><p><span class="RktPn">(</span><span class="RktSym">sum</span><span class="stt"> </span><span class="RktSym">JANUS</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">sum</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="stt"> </span><span class="RktSym">JANUS</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">sum</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span><span class="stt"> </span><span class="RktSym">JANUS</span><span class="stt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._~3c%29%29" class="RktValLink" data-pltdoc="x">&lt;</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></li></ul></div><div class="SIntrapara">Assuming <span class="RktSym">sum</span> adds the numbers in a list from left to right,
explain what these expressions compute. What do you think of the results?</div></p><p><div class="SIntrapara">Generic advice on inexact calculations tells programmers to start additions
with the smallest numbers. While adding a big number to two small numbers
might yield the big one, adding small numbers first creates a large one,
which might change the outcome:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="hspace">&nbsp;</span><span class="RktVal">#i53.0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i9007199254740992.0</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktVal">#i1.0</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="hspace">&nbsp;</span><span class="RktVal">#i53.0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i9007199254740992.0</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktVal">#i1.0</span><span class="hspace">&nbsp;</span><span class="RktVal">#i1.0</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="hspace">&nbsp;</span><span class="RktVal">#i53.0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i9007199254740994.0</span></p></td></tr></table></blockquote></div><div class="SIntrapara">This trick may <span style="font-weight: bold">not</span> work; see the <span class="RktSym">JANUS</span> interactions above.</div></p><p><div class="SIntrapara">In a language such as ISL+, you can convert the numbers to exact
rationals, use exact arithmetic on those, and convert the result back:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._exact-~3einexact%29%29" class="RktValLink" data-pltdoc="x">exact-&gt;inexact</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._inexact-~3eexact%29%29" class="RktValLink" data-pltdoc="x">inexact-&gt;exact</a></span><span class="hspace">&nbsp;</span><span class="RktSym">JANUS</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Evaluate this expression and compare the result to the three sums
above. What do you think now about advice from the web? <a href="i4-5.html#%28counter._%28exercise._ex~3ajanus%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3ajanus2))"></a><span style="font-weight: bold">Exercise</span>&nbsp;420. <span class="RktSym">JANUS</span> is just a fixed list, but take a look at
this function: <a name="(idx._(gentag._589))"></a>
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">O</span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">&gt;</a></span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28form._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace">&nbsp;</span><span class="RktVal">#i-0.99</span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">O</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</spa
first <span class="RktSym">n</span> elements of a mathematical series. It is best understood as a graph,
like the one in <a href="i4-5.html#%28counter._%28figure._fig~3aoscillate%29%29" data-pltdoc="x">figure&nbsp;<span class="FigureRef">145</span></a>. Run <span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="stt"> </span><span class="RktVal">15</span><span class="RktPn">)</span> in
DrRacket and inspect the result.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><span class="Smaller"><img src="pict_179.png" alt="image" width="400" height="400"/></span></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aoscillate))" x-target-lift="Figure"></a>Figure&nbsp;145: </span>The graph of <span class="RktSym">oscillate</span></span></p></blockquote><p><div class="SIntrapara">Summing its results from left to right computes a different result than from
right to left:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace">&nbsp;</span><span class="RktVal">#i1000.0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i-0.49746596003269394</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace">&nbsp;</span><span class="RktVal">#i1000.0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i-0.49746596003269533</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Again, the difference may appear to be small until we see the context:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace">&nbsp;</span><span class="RktVal">1e+16</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace">&nbsp;</span><span class="RktVal">#i1000.0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace">&nbsp;</span><span class="RktVal">1e+16</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace">&nbsp;</span><span class="RktVal">#i1000.0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">#i14.0</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Can this difference matter? Can we trust computers? <a href="i4-5.html#%28counter._%28exercise._ex~3ajanus2%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p>The question is which numbers programmers should use in their programs if
they are given a choice. The answer depends on the context, of course. In
the world of financial statements, numerical constants should be
interpreted as exact numbers, and computational manipulations of financial
statements ought to be able to rely on the exactness-preserving nature of
mathematical operations. After all, the law cannot accommodate the serious
errors that come with inexact numbers and their operations. In scientific
computations, however, the extra time needed to produce exact results might
impose too much of a burden. Scientists therefore tend to use inexact
numbers but carefully analyze their programs to make sure that the
numerical errors are tolerable for their uses of the outputs of programs.</p><div class="navsetbottom"><span class="navleft"><div class="nosearchform"></div>&nbsp;&nbsp;<span class="tocsettoggle">&nbsp;&nbsp;<a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright">&nbsp;&nbsp;<a href="part_four.html" title="backward to &quot;IV Intertwined Data&quot;" data-pltdoc="x">&larr; prev</a>&nbsp;&nbsp;<a href="index.html" title="up to &quot;How to Design Programs, Second Edition&quot;" data-pltdoc="x">up</a>&nbsp;&nbsp;<a href="part_five.html" title="forward to &quot;V Generative Recursion&quot;" data-pltdoc="x">next &rarr;</a></span>&nbsp;</div></div></div><div id="contextindicator">&nbsp;</div></body></html>