Scheme's built-in procedures display and write
write out inexact real numbers in a form that is, from a certain point of
view, quite natural and elegant: Exactly enough digits are printed after
the decimal point to enable Scheme's read procedure to recover
the same value from the printed representation -- no more, and no fewer.
However, this representation is unsuitable for some applications. For instance, one often wants to print some numbers in a vertical column, right-justified and with the same number of decimal places showing in each number. For example, if the numbers represent quantities of American money, one almost always wants to display exactly two decimal places:
$ 182.00 $ 182
8.68 8.675
1383.10 1383.1
90.00 rather than 89.996274
When we tell Scheme to print out a number, then, we'd like to be able to specify (1) the number of places after the decimal point, and also (2) the width, in columns, of the field into which we want the numeral placed. Scheme can then right-justify the numerals -- that is, line them up along at their right edge -- by padding each one with an appropriate number of spaces on the left.
Standard Scheme does not provide a procedure that performs this kind of
formatted output, but it does provide the resources we need in order to
write one of our own. That's the project: to define a procedure
write-real that takes three arguments -- a real number to be
printed, a ``field width'' indicating how many characters should be printed
altogiether, and a ``fraction length'' indicating how many characters
should be printed after the decimal point -- and writes out the appropriate
numeral. For instance, the call (write-real 3.14159 12 3)
should write out seven spaces, the digit 3, a decimal point,
and the digits 142 -- in other words, the numeral
3.142, right-justified in a field of width twelve.
It's a little tricky. If the number to be printed is negative, you have to remember to save space for the sign. If the number has more decimal places than the fraction-length argument specifies, you have to round off the last digit to be printed. If you round up from a 9 in the last digit, you have to change digits farther to the left in the numeral; sometimes every digit is different (as when 89.996274 was rounded off to 90.00 above). You have to decide what to do if the number won't fit into the field width provided.
A definition of such a procedure, together with the definitions of other procedures that help it work, is available in /u2/stone/courses/scheme/html/writing-reals.ss -- but (since this is a project) it's incomplete. Your part is to read the definitions, try to understand what's going on, and fill in the missing pieces.
Copy /u2/stone/courses/scheme/html/writing-reals.ss into a
similarly named file in your account. Load it into XEmacs and study it.
The bodies of the explode-into-digits,
list-of-digits?, and digits->chars procedures
are missing. Write and test them.
Test and experiment with the other procedures in the program, including
write-real. Write a procedure that prints a list of real
numbers as a right-justified column of numerals with two decimal places
showing, as in the example above.
If it is given a number that won't fit into a field of the specified width,
the write-real procedure prints out as many characters as it
needs (so the field-width parameter is more like a piece of
advice than an unbreakable constraint). Modify the definition of
write-real so that in this situation it instead prints a
string of asterisks equal in length to the specified field-width.
Develop a similar write-integer procedure that takes two
arguments -- an integer and a field-width -- and displays the integer as a
whole number, right-justified in a field of the specified width.
This document is available on the World Wide Web as
http://www.math.grin.edu/courses/Scheme/fall-1997/writing-reals-project.html
created October 15, 1997
last revised October 16, 1997