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.
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 ;; ==> 1/16 ;; In base sixteen, "10" is sixteen. #xb/a ;; ==> 11/10 ;; ... et cetera
For what the "#e" and "#i" are all about, read on.
1200 ;; ==> 1200 12## ;; ==> 1200. ;; The decimal point means Scheme ;; thinks the number is inexact.
You have already seen many of the predicates and other procedures that work with numbers in earlier tutorials. I will mention some of the previous ones again here, and will add a few new ones.
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:
(e::derationalize 4/3) ;; ==> 1.3333333333333333 (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 (string->number "137/42") ;; ==> 137/42 (number->string 42) ;; ==> "42" (number->string 42 10) ;; ==> "42" (number->string 42 2) ;; ==> "101010" (number->string 42 8) ;; ==> "52" (number->string 42 16) ;; ==> "2a" (number->string 42/1 16) ;; ==> "2a/1"
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
(except for here) procedure to print out numbers with Roman numerals. The
procedure is called "e::umber-nay->ing-stray". It takes one argument -- a
number -- and if that number is an exact integer in the range from
0 through 3999 (inclusive), it will print it out in Roman numerals. It will
print all other numbers in the same manner that "number->string" would when it
is printing in base ten.
(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)