246 lines
89 KiB
HTML
246 lines
89 KiB
HTML
|
<!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,"tocview_0");">▼</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"> </span> How to Program</a></td></tr><tr><td align="right">I </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 </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 </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 </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 </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 </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"> </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,"tocview_1");">►</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’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—<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’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’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"> </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"> -> </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"> </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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">e</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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"> </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"> </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"><=</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktVal">99</span><span class="RktPn">)</span><span class="hspace"> </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"><=</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym">e</span><span class="hspace"> </span><span class="RktVal">99</span><span class="RktPn">)</span><span class="hspace"> </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"> </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"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://do
|
||
|
a data representation in ISL+ and by running some experiments. Let’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"> </span><span class="RktSym">inex</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">mantissa</span><span class="hspace"> </span><span class="RktSym">sign</span><span class="hspace"> </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"> </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"> </span><span class="hspace"> </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"> </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"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">1</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</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"> </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 <span class="FigureRef">143</span></a>. The figure also defines
|
||
|
<span class="RktSym">inex->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’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"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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">> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">120</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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">> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">50</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </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">> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </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->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"> </span><span class="RktSym">MAX-POSITIVE</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">99</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktSym">MIN-POSITIVE</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </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"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">13</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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—<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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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’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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">55</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">55</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">11</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">56</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">56</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">11</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">16</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">20</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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’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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">27</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">7</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">19</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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> 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"> </span><span class="RktPn">(</span><span class="RktSym">inex+</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">11</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </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> 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’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> 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"> </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’t be represented because the exponent 500 won’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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">50</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">99</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">50</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktVal">100</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </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’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> 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"> </span><span class="RktMeta"></span><span class="RktVal">#i10.0</span><span class="RktMeta"></span><span class="hspace"> </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"> </span><span class="RktMeta"></span><span class="RktVal">#i10.</span><span class="RktMeta"></span><span class="hspace"> </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"> </span><span class="RktMeta"></span><span class="RktSym">n</span><span class="RktMeta"></span><span class="hspace"> </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’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’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"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-inex</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </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"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="hspace"> </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> 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"> </span><span class="RktMeta"></span><span class="RktVal">#i10.0</span><span class="RktMeta"></span><span class="hspace"> </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"> </span><span class="RktMeta"></span><span class="RktVal">#i10.</span><span class="RktMeta"></span><span class="hspace"> </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"> </span><span class="RktMeta"></span><span class="RktSym">n</span><span class="RktMeta"></span><span class="hspace"> </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 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’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’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—<wbr></wbr>using Racket—<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’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> 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> 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"> </span><span class="RktSym">inex</span><span class="hspace"> </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"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktSym">exac</span><span class="hspace"> </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"> </span><span class="RktVal">1</span><span class="hspace"> </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"> </span><span class="RktSym">JANUS</span></td></tr><tr><td><span class="hspace"> </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"> </span><span class="RktVal">31.0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i2e+34</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i-1.2345678901235e+80</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">2749.0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-2</span>939234.0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i-2e+33</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i3.2e+270</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">17.0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i-2.4e+270</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i4.2344294738446e+170</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">1.0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#i-8e+269</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">0.0</span></td></tr><tr><td><span class="hspace"> </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 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> 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’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 <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"><</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">> </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"> </span><span class="RktVal">2</span><span class="hspace"> </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">> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </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"> </span><span class="RktVal">#i1.0</span><span class="hspace"> </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"> </span><span class="RktVal">2</span><span class="hspace"> </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">> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </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"> </span><span class="RktVal">#i1.0</span><span class="hspace"> </span><span class="RktVal">#i1.0</span><span class="hspace"> </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"> </span><span class="RktVal">2</span><span class="hspace"> </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->inexact</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </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"> </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->exact</a></span><span class="hspace"> </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> 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"> </span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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"> </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"> </span><span class="RktPn">(</span><span class="RktSym">O</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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"> </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">></a></span><span class="hspace"> </span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </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"> </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"> </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"> </span><span class="RktVal">#i-0.99</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">O</span><span class="hspace"> </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"> </span><span class="RktSym">i</span><span class="hspace"> </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 <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 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">> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace"> </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">> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </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"> </span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace"> </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">> </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"> </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"> </span><span class="RktVal">1e+16</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace"> </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"> </span><span class="hspace"> </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"> </span><span class="RktVal">1e+16</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum</span><span class="hspace"> </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"> </span><span class="RktPn">(</span><span class="RktSym">oscillate</span><span class="hspace"> </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> <span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="part_four.html" title="backward to "IV Intertwined Data"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "How to Design Programs, Second Edition"" data-pltdoc="x">up</a> <a href="part_five.html" title="forward to "V Generative Recursion"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html>
|