*One of a series of tutorials about Scheme in general and the Wraith Scheme interpreter in particular.*

Copyright © 2011
Jay Reynolds Freeman,
all rights reserved.

Personal Web Site:
http://JayReynoldsFreeman.com

EMail: Jay_Reynolds_Freeman@mac.com.

In Scheme, numbers are typed in forms that generally resemble the forms that
most people use every day. Therefore, there is one simple truth that you should
remember: ** In Scheme, pretty much everything that looks like a number
actually is a number.** There are a few details beyond that, and there
are some procedures involving numbers that you might want to know about, but
mostly it simple: As far as Scheme is concerned, all of the
following are numbers, and Scheme will understand their values to be just what
you would expect if you lived in a world that had never heard of computers and
programming languages.

1 42 42. 42.0000 -1 1/2 1.5 1+3i 3i -i

Now let's see about some details.

- Scheme uses the period character, ".", as the decimal point, to separate the integer part of a number from the fractional part. Thus Scheme understands 1.5 as the number one and one-half. In some parts of the world, it would be normal to write one and one-half with a comma, as "1,5", but Scheme will not understand you if you do that.
- Scheme does not use any character to group digits in bunches of three in
large numbers. For example, Scheme will not understand any of the following
as numbers.
5,000,000 1.234.567.890 9 876 543 210

Instead, you should use

5000000 1234567890 9876543210

1.23e3 ;; 1230 1.23e+3 ;; 1230 1.23e-3 ;; 0.00123

Actually, several other letters will may also indicate an exponent; "d", "f", "l" and "s" will do just as well. They are part of the Scheme standard for use by Scheme implementations that have several different ways to store floating-point numbers internally, with different amounts of precision. Wraith Scheme only uses one way (IEEE 64-bit floats, if you are curious), so it makes no difference which of these letters you use. I use "e" out of personal habit.

All of the letters used for the exponent can be capitalized.

1.23E3 ;; 1230 1.23E+3 ;; 1230 1.23E-3 ;; 0.00123

1 + 3i 3 i 1 / 2 9 876 543 210 1.23 e 3

It turns out that restricting the range of the numerators and denominators of rational numbers is rather annoying if you are trying to do engineering or scientific computations -- such work usually overflows the size limits pretty quickly, so you lose the benefits of high precision, and furthermore, the output of such calculations is usually easier to understand if it is printed out using decimal format rather than using fractions. Thus I arranged that Wraith Scheme's procedures do not return results in which the numerator and denominator are remembered separately unless all of their inputs are that kind of number; and many procedures cannot even do that.

i

Scheme will ** not** think you are typing the complex number "i".
Scheme will think you are typing a variable whose name is "i", and will attempt
to look up its value in the usual manner. (That was a design decision on the
part of the folks who designed the Scheme language, and I suppose it could
have gone the other way, but it didn't.) If you want the complex number "i",
type

+i

with a plus sign.

42@1.5708

is not too far from

0+42i

since 1.5708 is not far from pi/2.

Thus in Scheme, all of the following are correct ways to write the number commonly known as forty-two.

42 #d42 #x2a #x2A ;; Capitals and lower-case both work for hexadecimal digits. #o52 #b101010

Any sign must precede the radix prefix.

-#x2a ;; This works. #x-2a ;; This does not work.

In bases other than ten, Scheme only understands numbers that have neither decimal points nor exponents

#x2a.0 ;; This does not work. #o52e1 ;; This does not work.

Note, however, that the kind of fractions that Scheme reads are written as one integer divided by another, and in that case, other bases are fine.

#x1/10 ;; ==> #e0.0625 ;; In base sixteen, "10" is sixteen. #xb/a ;; ==> #i1.1000000000000001 ;; e.g., 11/10

For what the "#e" and "#i" are all about, read on.

- Any number with a decimal point in it is inexact, unless prefixed with "#e" or "#E".
- Any number without a decimal point is exact, unless prefixed with "#i" or "#I".
- You may use exactness prefixes yourself, to override the defaults just given, when you wish to specify explicitly whether a number is supposed to be exact or inexact.
- Exactness prefixes go in the same places that radix prefixes go -- before the number, after any sign, no whitespace allowed.
- A number may have both an exactness prefix and a radix prefix, and they may be in either order.

1200 ;; ==> 1200 12## ;; ==> 1200. ;; The decimal point means Scheme ;; thinks the number is inexact.

To begin with, there are predicates "exact?" and "inexact?", to access the information stored with each number about whether it is exact or not.

(exact? 1) ;; ==> #t (exact? 1.) ;; ==> #f (inexact? 1) ;; ==> #f (inexact? 1.) ;; ==> #t

Procedures "real-part", "imag-part", "magnitude", and "angle" extract information about a complex number.

(real-part 42+137i) ;; ==> 42 (imag-part 42+137i) ;; ==> 137 (magnitude 42+137i) ;; ==> 143.29340529138108 (angle 42+137i) ;; ==> 1.2733235621137906 ;; In radians, remember.

There are procedures to make a complex number either from its real and imaginary parts, or from its magnitude and angle.

(make-rectangular 42 137) ;; ==> 42+137i (make-polar 143.29340529138108 1.2733235621137906) ;; ==> 41.999999999999986+137.i

Procedures "numerator" and "denominator" extract the numerator and denominator from a number which remembers those two quantities separately. Procedure "rationalize" finds the simplest fraction (in the sense of smallest denominator) within a given distance of any real number. For example:

(rationalize (sqrt 2) 0.01) ;; ==> #i17/12 (rationalize (sqrt 2) 0.001) ;; ==> #i41/29 (rationalize (sqrt 2) 0.000001) ;; ==> #i1393/985

Procedure "e::derationalize" returns the 64-bit floating-point number obtained by dividing the numerator of a fraction by its denominator. Procedure "e::make-long-ratnum" allows you to construct a "fraction" by providing its numerator and denominator as arguments to a procedure rather than typing in the fraction as a literal constant:

(define num 42) ;; ==> num (define denom 137) ;; ==> denom (e::make-long-ratnum num denom) ;; ==> 42/137

Two procedures allow for converting between strings and numbers. Both take an optional second argument, a number that must be 2, 8, 10 or 16, to specify the base in which the conversion is to take place. If no second argument is present the base will be taken to be 10.

(string->number "42") ;; ==> 42 (string->number "#i42") ;; ==> 42. (string->number "#x2a" 16) ;; ==> 42 (string->number "2a" 16) ;; ==> 42 (string->number "#i1+3i") ;; ==> 1+3i (number->string 42) ;; ==> "42" (number->string 42 10) ;; ==> "42" (number->string 42 2) ;; ==> "101010" (number->string 42 8) ;; ==> "52" (number->string 42 16) ;; ==> "2a"

Note that "number->string" never prints a radix prefix.

As a reward for reading the tutorials this far, I will tell you a secret. Wraith
Scheme has as an enhancement, an ** undocumented** procedure to print out numbers
with Roman numerals. The procedure is called "e::umber-nay->ing-stray". It takes one
argument -- a number -- and

(e::umber-nay->ing-stray 42) ;; ==> "XLII"

The name "e::umber-nay->ing-stray" is in Pig Latin, which is a joke language that most Americans learned when we were in grammar school and should have been studying but weren't. If you have never heard of it, don't worry. It kind of makes sense, though; I mean, if you talk to a computer in any kind of Latin, wouldn't you expect it to use Roman numerals? This procedure is undocumented because my sense of whimsy includes leaving little tidbits of harmless unexpected features lying around in my programs for you to find, and yes, there are others.

I rather suspect that no other Scheme implementation has any procedures with names like "e::umber-nay->ing-stray". So if you go around speaking Pig Latin to other members of the Scheme community, they will probably look at you funny. If that happens, I would be very much obliged if you did not mention my name.

-- Jay Reynolds Freeman (Jay_Reynolds_Freeman@mac.com)