Fixed-size Number Arithmetic

Suppose we can use four digits to represent numbers. If we represent natural numbers, the representable range is 0 ...9999. Alternatively we could represent 10,000 fractions between 0 and 1 with that many digits. In either case, this is a rather small range of numbers and not useful for most scientific or business computations. We can represent a larger range of numbers if we use a different notation for numbers instead. In science, for example, we encounter so-called scientific notation, which represents numbers as two parts:
  1. a <#67872#><#43003#>MANTISSA<#43003#><#67872#>, which is a base number and
  2. an <#67873#><#43004#>EXPONENT<#43004#><#67873#>, which is used to determine a 10-based factor.
For pure scientific notation, the base is between 0 and 9. We relax this constraint and just write numbers as

#displaymath74028#

where <#43006#>m<#43006#> is the mantissa and <#43007#>e<#43007#> the exponent. For example, one representation of 1200 with this scheme is

#displaymath74030#

another one is

#displaymath74032#

In general, a number has several equivalents in mantissa-exponent representation. We can also use negative exponents, which adds fractions at the cost of one extra piece of data: the sign of the exponent. For example,

#displaymath74034#

stands for

#displaymath74036#

As before, the fraction has several different representations in the new notation. To use a form of mantissa-exponent notation for our problem, we must decide how many digits we wish to use for the representation of the mantissa and how many for the exponent. Here we use two for each and a sign for the exponent; other choices are possible. Given this decision, we can still represent 0 as

#displaymath74038#

The maximal number we can represent is

#displaymath74040#

which is 99 followed by 99 0's. If we use negative exponents in addition to positive ones, we can also represent

#displaymath74042#

which is a small number close to <#43013#>0<#43013#>. Thus, we can now represent a vastly larger range of numbers with four digits and a sign than before. But, this improvement comes with its own problems.


<#71689#>;; <#67874#><#43018#>create-inex<#43018#> <#43019#>:<#43019#> <#43020#>N<#43020#> <#43021#>N<#43021#> <#43022#>N<#43022#> <#43023#><#43023#><#43024#>-;SPMgt;<#43024#><#43025#><#43025#> <#43026#>inex<#43026#><#67874#><#71689#>
<#71690#>;; to make an instance of <#67875#><#43027#>inex<#43027#><#67875#> after checking the appropriateness<#71690#> 
<#43028#>;; of the arguments<#43028#> 
<#43029#>(d<#43029#><#43030#>efine<#43030#> <#43031#>(create-inex<#43031#> <#43032#>m<#43032#> <#43033#>s<#43033#> <#43034#>e)<#43034#> 
  <#43035#>(c<#43035#><#43036#>ond<#43036#> 
    <#43037#>[<#43037#><#43038#>(and<#43038#> <#43039#>(;SPMlt;=<#43039#> <#43040#>0<#43040#> <#43041#>m<#43041#> <#43042#>99)<#43042#> <#43043#>(;SPMlt;=<#43043#> <#43044#>0<#43044#> <#43045#>e<#43045#> <#43046#>99)<#43046#> <#43047#>(or<#43047#> <#43048#>(=<#43048#> <#43049#>s<#43049#> <#43050#>+1)<#43050#> <#43051#>(=<#43051#> <#43052#>s<#43052#> <#43053#>-1)))<#43053#> 
     <#43054#>(make-inex<#43054#> <#43055#>m<#43055#> <#43056#>s<#43056#> <#43057#>e)]<#43057#> 
    <#43058#>[<#43058#><#43059#>else<#43059#> 
     <#43060#>(error<#43060#> <#43061#>'<#43061#><#43062#>make-inex<#43062#> <#43063#>``(<#43063#>;SPMlt;<#43064#>=<#43064#> <#43065#>0<#43065#> <#43066#>m<#43066#> <#43067#>99),<#43067#> <#43068#>+<#43068#><#43069#>1<#43069#> <#43070#>or<#43070#> <#43071#>-1,<#43071#> <#43072#>(<#43072#>;SPMlt;<#43073#>=<#43073#> <#43074#>0<#43074#> <#43075#>e<#43075#> <#43076#>99)<#43076#> <#43077#>expected'')]<#43077#><#43078#>))<#43078#> 
<#72259#>;; <#71691#><#67876#><#43079#>inex<#43079#><#67876#><#67877#><#43080#><#43080#><#43081#>-;SPMgt;<#43081#><#43082#><#43082#><#67877#><#67878#><#43083#>number<#43083#><#67878#> <#43084#>:<#43084#> <#43085#>inex<#43085#> <#43086#><#43086#><#43087#>-;SPMgt;<#43087#><#43088#><#43088#> <#43089#>number<#43089#><#71691#><#72259#> 
<#71692#>;; to convert an <#67879#><#43090#>inex<#43090#><#67879#> into its numeric equivalent <#71692#> 
<#43091#>(d<#43091#><#43092#>efine<#43092#> <#43093#>(<#43093#><#67880#><#43094#>inex<#43094#><#67880#><#67881#><#43095#><#43095#><#43096#>-;SPMgt;<#43096#><#43097#><#43097#><#67881#><#67882#><#43098#>number<#43098#><#67882#> <#43099#>an-inex)<#43099#> 
  <#43100#>(*<#43100#> <#43101#>(inex-mantissa<#43101#> <#43102#>an-inex)<#43102#> 
     <#43103#>(expt<#43103#> <#43104#>10<#43104#> <#43105#>(*<#43105#> <#43106#>(inex-sign<#43106#> <#43107#>an-inex)<#43107#> <#43108#>(inex-exponent<#43108#> <#43109#>an-inex)))))<#43109#> 
<#43113#>Figure: Functions for inexact representations<#43113#>
To understand the problems, it is best to agree on a fixed representation schema and to experiment with the number representations. Let's represent a fixed-size number with a structure that has three fields:
<#43119#>(define-struct<#43119#> <#43120#>inex<#43120#> <#43121#>(mantissa<#43121#> <#43122#>sign<#43122#> <#43123#>exponent))<#43123#>
The first and last field contain the mantissa and exponent of the number, the <#67883#><#43127#>sign<#43127#><#67883#> field is <#67884#><#43128#>+1<#43128#><#67884#> or <#67885#><#43129#>-1<#43129#><#67885#> and represents the sign of the exponent. This sign field enables us to represent numbers between <#67886#><#43130#>0<#43130#><#67886#> and <#67887#><#43131#>1<#43131#><#67887#>. Here is the data definition:
An <#67888#><#43133#>inex<#43133#><#67888#> is a structure:

<#71693#><#67889#><#43134#>(make-inex<#43134#>\ <#43135#>m<#43135#>\ <#43136#>s<#43136#>\ <#43137#>e)<#43137#><#67889#><#71693#> where <#67890#><#43138#>m<#43138#><#67890#> and <#67891#><#43139#>e<#43139#><#67891#> are natural numbers between <#67892#><#43140#>0<#43140#><#67892#> and <#67893#><#43141#>99<#43141#><#67893#> and <#67894#><#43142#>s<#43142#><#67894#> is <#67895#><#43143#>+1<#43143#><#67895#> or <#67896#><#43144#>-1<#43144#><#67896#>.

Because the conditions on the fields of an <#67897#><#43146#>inex<#43146#><#67897#> structure are so stringent, we use the function <#67898#><#43147#>create-inex<#43147#><#67898#> to create these structures. Figure~#figinexactconstruct#43148> contains the function definition for <#67899#><#43149#>create-inex<#43149#><#67899#>. The figure also defines the function <#71694#><#67900#><#43150#>inex<#43150#><#67900#><#67901#><#43151#><#43151#><#43152#>-;SPMgt;<#43152#><#43153#><#43153#><#67901#><#67902#><#43154#>number<#43154#><#67902#><#71694#>, which turns <#67903#><#43155#>inex<#43155#><#67903#>s into numbers according to the principles of our new notation. Let's translate the above example, <#67904#><#43156#>1200<#43156#><#67904#>, into our Scheme representation:
<#43161#>(create-inex<#43161#> <#43162#>12<#43162#> <#43163#>+1<#43163#> <#43164#>2)<#43164#>
The alternative representation, #tex2html_wrap_inline74048#, is illegal in our Scheme world, however. If we evaluate
<#43172#>(create-inex<#43172#> <#43173#>120<#43173#> <#43174#>+1<#43174#> <#43175#>1)<#43175#>
we get an error message because the arguments don't satisfy the stated data contract. For other numbers, though, we can find two <#67905#><#43179#>inex<#43179#><#67905#> equivalents. One example is <#67906#><#43180#>0.0000000000000000005<#43180#><#67906#>, which we can express as
<#43185#>(create-inex<#43185#> <#43186#>50<#43186#> <#43187#>-1<#43187#> <#43188#>20)<#43188#>
<#43189#>;and<#43189#> 
<#43190#>(create-inex<#43190#> <#43191#>5<#43191#> <#43192#>-1<#43192#> <#43193#>19)<#43193#> 
Confirm the equivalence of these two representations with <#71695#><#67907#><#43197#>inex<#43197#><#67907#><#67908#><#43198#><#43198#><#43199#>-;SPMgt;<#43199#><#43200#><#43200#><#67908#><#67909#><#43201#>number<#43201#><#67909#><#71695#>. The range of <#67910#><#43202#>inex<#43202#><#67910#> numbers is vast:
<#43207#>(define<#43207#> <#43208#>MAX-POSITIVE<#43208#> <#43209#>(make-inex<#43209#> <#43210#>99<#43210#> <#43211#>+1<#43211#> <#43212#>99))<#43212#>
<#43213#>(define<#43213#> <#43214#>MIN-POSITIVE<#43214#> <#43215#>(make-inex<#43215#> <#43216#>1<#43216#> <#43217#>-1<#43217#> <#43218#>99))<#43218#> 
That is, we can represent large numbers that consist of up to 101 digits in the standard decimal notation; we can also represent small positive fractions smaller than <#67911#><#43222#>1<#43222#><#67911#> down to the fraction 1 over #tex2html_wrap_inline74050# with 99 zeros. The appearances, however, are deceiving. Not all real numbers in the range between 0 and <#67912#><#43223#>MAX-POSITIVE<#43223#><#67912#> can be translated into an <#67913#><#43224#>inex<#43224#><#67913#> structure. In particular, any positive number less than

#displaymath74052#

has no equivalent <#67914#><#43226#>inex<#43226#><#67914#> structure. Similarly, the <#67915#><#43227#>inex<#43227#><#67915#> representation has gaps in the middle. For example, the successor of

<#43232#>(create-inex<#43232#> <#43233#>12<#43233#> <#43234#>+1<#43234#> <#43235#>2)<#43235#>
is
<#43243#>(create-inex<#43243#> <#43244#>13<#43244#> <#43245#>+1<#43245#> <#43246#>2)<#43246#>
The first <#67916#><#43250#>inex<#43250#><#67916#> structure corresponds to <#67917#><#43251#>1200<#43251#><#67917#>, the second one to <#67918#><#43252#>1300<#43252#><#67918#>. Numbers in the middle, such as <#67919#><#43253#>1240<#43253#><#67919#> or <#67920#><#43254#>1260<#43254#><#67920#>, can only be represented as one or the other. The standard choice is to round the number and to the closest representable equivalent. In short, we must approximate such mathematical numbers as we translate into a chosen representation. Finally, we must also consider arithmetic operations on <#67921#><#43255#>inex<#43255#><#67921#> structures. Adding two <#67922#><#43256#>inex<#43256#><#67922#> representations with the same exponent means adding the two mantissas:
  <#43261#>(inex+<#43261#> <#43262#>(create-inex<#43262#> <#43263#>1<#43263#> <#43264#>+1<#43264#> <#43265#>0)<#43265#>
         <#43266#>(create-inex<#43266#> <#43267#>2<#43267#> <#43268#>+1<#43268#> <#43269#>0))<#43269#> 
<#43270#>=<#43270#> <#43271#>(create-inex<#43271#> <#43272#>3<#43272#> <#43273#>+1<#43273#> <#43274#>0)<#43274#> 
Translated into mathematical notation, we have

#displaymath74054#

When the addition of two mantissas yields too many digits, we may have to find a suitable representation. Consider the example of adding

#displaymath74056#

to itself. Mathematically we get

#displaymath74058#

but we can't just translate this number naively into our chosen representation because 110 ;SPMgt; 99. The proper corrective action is to represent the result as

#displaymath74062#

Or, translated into Scheme, we must ensure that <#67923#><#43281#>inex+<#43281#><#67923#> computes as follows:

  <#43286#>(inex+<#43286#> <#43287#>(create-inex<#43287#> <#43288#>55<#43288#> <#43289#>+1<#43289#> <#43290#>0)<#43290#>
         <#43291#>(create-inex<#43291#> <#43292#>55<#43292#> <#43293#>+1<#43293#> <#43294#>0))<#43294#> 
<#43295#>=<#43295#> <#43296#>(create-inex<#43296#> <#43297#>11<#43297#> <#43298#>+1<#43298#> <#43299#>1)<#43299#> 
More generally, if the mantissa of the result is too large, we must divide it by <#67924#><#43303#>10<#43303#><#67924#> and increase the exponent by one. Sometimes the result contains more mantissa digits than we can represent. In those cases, <#67925#><#43304#>inex+<#43304#><#67925#> must round to the closest equivalent in the <#67926#><#43305#>inex<#43305#><#67926#> world. For example:
  <#43310#>(inex+<#43310#> <#43311#>(create-inex<#43311#> <#43312#>56<#43312#> <#43313#>+1<#43313#> <#43314#>0)<#43314#>
         <#43315#>(create-inex<#43315#> <#43316#>56<#43316#> <#43317#>+1<#43317#> <#43318#>0))<#43318#> 
<#43319#>=<#43319#> <#43320#>(create-inex<#43320#> <#43321#>11<#43321#> <#43322#>+1<#43322#> <#43323#>1)<#43323#> 
This correspons to the precise calculation:

#displaymath74064#

Because the result has too many mantissa digits, the integer division of the result mantissa by <#67927#><#43329#>10<#43329#><#67927#> produces an approximate result:

#displaymath74066#

This is an example of the many approximations that make <#67928#><#43331#>INEXACT ARITHMETIC<#43331#><#67928#> inexact. We can also multiply numbers represented as <#67929#><#43332#>inex<#43332#><#67929#> structures. Recall that

#displaymath74068#

Thus, we get:

#displaymath74070#

or, in Scheme notation:

  <#43344#>(inex*<#43344#> <#43345#>(create-inex<#43345#> <#43346#>2<#43346#> <#43347#>+1<#43347#> <#43348#>4)<#43348#>
         <#43349#>(create-inex<#43349#> <#43350#>8<#43350#> <#43351#>+1<#43351#> <#43352#>10))<#43352#> 
<#43353#>=<#43353#> <#43354#>(make-inex<#43354#> <#43355#>16<#43355#> <#43356#>+1<#43356#> <#43357#>14)<#43357#> 
As with addition, things are not always straightforward. When the result has too many significant digits in the mantissa, <#67930#><#43361#>inex*<#43361#><#67930#> has to increase the exponent:
  <#43366#>(inex*<#43366#> <#43367#>(create-inex<#43367#> <#43368#>20<#43368#> <#43369#>-1<#43369#> <#43370#>1)<#43370#>
         <#43371#>(create-inex<#43371#>  <#43372#>5<#43372#> <#43373#>+1<#43373#> <#43374#>4))<#43374#> 
<#43375#>=<#43375#> <#43376#>(create-inex<#43376#> <#43377#>10<#43377#> <#43378#>+1<#43378#> <#43379#>4)<#43379#> 
In the process, <#67931#><#43383#>inex*<#43383#><#67931#> will introduce an approximation if the true mantissa doesn't have an exact equivalent in the class of <#67932#><#43384#>inex<#43384#><#67932#> structures:
  <#43389#>(inex*<#43389#> <#43390#>(create-inex<#43390#> <#43391#>27<#43391#> <#43392#>-1<#43392#> <#43393#>1)<#43393#>
         <#43394#>(create-inex<#43394#>  <#43395#>7<#43395#> <#43396#>+1<#43396#> <#43397#>4))<#43397#> 
<#43398#>=<#43398#> <#43399#>(create-inex<#43399#> <#43400#>19<#43400#> <#43401#>+1<#43401#> <#43402#>4)<#43402#> 

<#43408#>Exercise 33.1.1<#43408#> Develop the function <#67933#><#43410#>inex+<#43410#><#67933#>, which adds <#67934#><#43411#>inex<#43411#><#67934#> representations that have the same exponent. The function must be able to deal with examples that increase the exponent. Furthermore, it must signal its own error if the result is out of range for <#67935#><#43412#>inex<#43412#><#67935#> representations.

<#43413#>Challenge<#43413#>:\ Extend <#67936#><#43414#>inex+<#43414#><#67936#> so that it can deal with inputs whose exponents differ by <#67937#><#43415#>1<#43415#><#67937#>:

  <#43420#>(inex+<#43420#> <#43421#>(create-inex<#43421#> <#43422#>1<#43422#> <#43423#>+1<#43423#> <#43424#>0)<#43424#> <#43425#>(create-inex<#43425#> <#43426#>1<#43426#> <#43427#>-1<#43427#> <#43428#>1))<#43428#>
<#43429#>=<#43429#> <#43430#>(create-inex<#43430#> <#43431#>11<#43431#> <#43432#>-1<#43432#> <#43433#>1)<#43433#> 
Do not attempt to deal with larger classes of inputs than that without reading the following subsection.~ external Solution<#67938#><#67938#> <#43442#>Exercise 33.1.2<#43442#> Develop the function <#67939#><#43444#>inex*<#43444#><#67939#>, which multiplies <#67940#><#43445#>inex<#43445#><#67940#> representations. The function must be able to deal with examples that increase the exponent. Furthermore, it must signal its own error if the result is out of range for <#67941#><#43446#>inex<#43446#><#67941#> representations.~ external Solution<#67942#><#67942#> <#43452#>Exercise 33.1.3<#43452#> The section illustrated how an inexact representation system for real numbers has gaps. For example, 1240 was represented as <#67943#><#43454#>(create-inex<#43454#><#43455#> <#43455#><#43456#>12<#43456#>\ <#43457#>+1<#43457#>\ <#43458#>2)<#43458#><#67943#> by rounding off the last significant digit of the mantissa. The problem is, round-off errors can accumulate. Develop the function <#67944#><#43459#>add<#43459#><#67944#>, which adds up <#67945#><#43460#>n<#43460#><#67945#> copies of <#67946#><#43461#>#<#43461#><#43462#>i1/185<#43462#><#67946#>. What is the result for <#67947#><#43463#>(add<#43463#>\ <#43464#>185)<#43464#><#67947#>? What should it be? What happens if we multiply the result of the second expression with a large number? Develop the function <#67948#><#43465#>sub<#43465#><#67948#>, which counts how often <#67949#><#43466#>1/185<#43466#><#67949#> can be subtracted from the argument until the argument is <#67950#><#43467#>0<#43467#><#67950#>. How often should the evaluation recur for <#67951#><#43468#>(sub<#43468#>\ <#43469#>1)<#43469#><#67951#> and <#67952#><#43470#>(sub<#43470#><#43471#> <#43471#><#43472#>#<#43472#><#43473#>i1.)<#43473#><#67952#> is evaluated? What happens in the second case? Why?~ external Solution<#67953#><#67953#>