Numbers

Categories of numbers

Scheme treats numbers slightly differently depending on whether they are integers (whole numbers), rational numbers (expressible as a ratio of integers), real numbers (corresponding to points on a number line), or complex numbers (corresponding to points on the plane determined by a real-number line and a perpendicular line for ``imaginary numbers'' -- the square roots of negative numbers). From the Scheme programmer's point of view, these categories of numbers are nested: all integers also qualify as rational numbers (5 is the same thing as 5/1); all rationals count as real numbers, and all real numbers as complex numbers. But, mathematically speaking, the converse inclusions do not generally hold. (3/4 is rational but not an integer, the square root of 2 is real but not rational, and the square root of -1 is complex but not real.)

Scheme supplies a predicate for each of these categories of numbers: integer?, rational?, real?, and complex?, respectively.

  1. Have Scheme confirm that 3/4 is a rational number but not an integer amd that (sqrt -1) is a complex number but not a real number.

Within each of these categories of numbers, Scheme distinguishes between exact numbers, which are guaranteed to be calculated and stored internally with complete accuracy (no rounding off, no approximations), and inexact numbers, which are stored internally in a form that conserves the computer's memory and permits faster computations, but allows small inaccuracies (and occasionally ones that are not so small) to creep in. Since there's no great advantage in obtaining an answer quickly if it may be incorrect, we shall avoid using inexact numbers in this course except when the data for our problems are themselves products of inexact measurement (as in exercise #1).

To determine whether Scheme is representing a particular number exactly or inexactly, use one of the predicates exact? and inexact?.

> (exact? 5/9)
#t
> (exact? 13.2)
#f
> (inexact? 13.2)
#t

Chez Scheme happens to store real numbers in such a way that any real number that can be named or computed also counts as rational. For instance, when Chez Scheme computes (sqrt 2), the value it returns is an inexact approximation to the correct value, and it turns out that Chez Scheme uses only rational numbers as approximations.

  1. Use Chez Scheme to confirm that the value it computes for (sqrt 2) is an inexact real that is also rational.

  2. Have Chez Scheme find the square of the square root of 2 and subtract 2 from the result. Ideally, the difference should be 0; why isn't it? How great is the difference?

The standard language definition for Scheme says that an implementation of the language does not have to support all these categories of numbers; it would be legal, for instance, to leave out complex numbers or to treat all numeric values as inexact. However, most implementations (including Chez Scheme) support all the kinds of numbers described here.

Numerals

When you write a numeral into a Scheme program or type one in as part of a definition or command to the interactive interface, you have some control over the category of the number represented.

One basic rule is that a numeral that contains a decimal point normally stands for an inexact number. Scheme assumes that you may have rounded off the last decimal place and takes this as implicit permission to use an approximate representation. If you want Scheme to interpret the numeral as an exact number, you can either convert it to a fraction -- for instance, changing 1.732 to 1732/1000 -- or attach the exactness prefix #e at the beginning of the numeral, making it #e1.732.

Conversely, a number written such as a sequence of digits (possibly with a sign at the beginning) or as a fraction normally stands for an exact number. If you want an inexact one, use an equivalent numeral with a decimal point or attach the inexactness prefix #i. (So 23/70 is an exact number, but #i23/70 is inexact.)

Scheme permits the use of a version of scientific notation, in which a real number is expressed as the product of some coefficient and some integer power of 10. For instance, the numeral 3.17e8 denotes the real number three hundred and seventeen million -- that is, 3.17 times ten to the eighth power. The part of the numeral that precedes the e is the coefficient; the part that follows indicates which power of ten the coefficient should be multiplied by. A number expressed in scientific notation is also inexact unless preceded by the exactness prefix. Scheme will use scientific notation when printing out an inexact number if its absolute value is either very large or very small.

  1. Write a Scheme numeral for 1.507 times ten to the fifteenth power, as an exact number. Have Scheme evaluate the numeral.

  2. Write a Scheme numeral for one-third, as an inexact number. Have Scheme evaluate the numeral.

Numerical procedures

The reading assignment for today included descriptions of more than fifty procedures for operating on numbers. (Figure 3.3 on page 76 of the textbook provides a more manageable list of the ones that are most commonly used.) I'll assume that you're more or less familiar with the list and just comment on a few features of them that you may want to take advantage of:

The addition and multiplication procedures, + and *, accept any number of operands. You can, for instance, ask Scheme to imitiate a cash register with a command like this one:

> (+ 1.19
      .43
      .43
     2.59
      .89
     1.39
     5.19
      .34 
  )
12.45

You can call the - procedure or the / procedure to operate on a single operand. The - procedure returns the additive inverse of a single operand (that is, its negative, the result of subtracting it from 0), and the / procedure returns the multiplicative inverse of a single operand (its reciprocal, the result of dividing 1 by it).

  1. Use Scheme to find the reciprocal of 3/5.

The log procedure, despite its name, computes natural (base e) logarithms rather than common (base ten) logarithms. You can convert a natural logarithm into a common logarithm by dividing it by the natural logarithm of 10.

  1. Define a Scheme procedure log10 that takes any positive real number as argument and returns its common logarithm, computing it by the strategy just suggested. Use your procedure to confirm that the common logarithm of one million is 6.

My kids' arithmetic textbooks are full of tedious-looking exercises like ``Find the smallest number that is an exact multiple of 1732, 680, and 2520.'' Scheme has built-in gcd (``greatest common divisor'' and lcm (``least common multiple'') procedures for such computations.

  1. Have Scheme find the smallest number that is an exact multiple of 1732, 680, and 2520.

If you're planning to use any of the trigonometric functions, bear in mind that Scheme measures all angles in radians, not degrees.

  1. Once around the circle is an angle of 360 degrees or, equivalently, 2pi radians. Define a Scheme procedure degrees->radians that takes the measure of an angle in degrees and converts it to radians (by multiplying or dividing by an appropriate conversion factor).

  2. Scheme doesn't provide a cotangent procedure cot. Define one, using the fact that the cotangent of a number is the reciprocal of its tangent.

  3. An integer m evenly divides an integer n if the remainder left over when n is divided by m is zero. Define a Scheme predicate evenly-divides? that takes two arguments, both assumed to be integers (and the second assumed to be non-zero), and returns #t if the first evenly divides the second and #f if it does not.


This document is available on the World Wide Web as

http://www.math.grin.edu/~stone/courses/scheme/numbers.html

created September 4, 1997
last revised September 5, 1997

John David Stone (stone@math.grin.edu)