[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4. Numbers

(This section is largely taken from the Revised^4 Report on the Algorithmic Language Scheme.)

Numerical computation has traditionally been neglected by the Lisp community. Until Common Lisp there was no carefully thought out strategy for organizing numerical computation, and with the exception of the MacLisp system little effort was made to execute numerical code efficiently. This report recognizes the excellent work of the Common Lisp committee and accepts many of their recommendations. In some ways this report simplifies and generalizes their proposals in a manner consistent with the purposes of Scheme.

It is important to distinguish between the mathematical numbers, the Scheme numbers that attempt to model them, the machine representations used to implement the Scheme numbers, and notations used to write numbers. This report uses the types number, complex, real, rational, and integer to refer to both mathematical numbers and Scheme numbers. Machine representations such as fixed point and floating point are referred to by names such as fixnum and flonum.

4.1 Numerical types  
4.2 Exactness  
4.3 Implementation restrictions  
4.4 Syntax of numerical constants  
4.5 Numerical operations  
4.6 Numerical input and output  
4.7 Fixnum and Flonum Operations  
4.8 Random Numbers  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 Numerical types

Mathematically, numbers may be arranged into a tower of subtypes in which each level is a subset of the level above it:

 
number
complex
real
rational
integer

For example, 3 is an integer. Therefore 3 is also a rational, a real, and a complex. The same is true of the Scheme numbers that model 3. For Scheme numbers, these types are defined by the predicates number?, complex?, real?, rational?, and integer?.

There is no simple relationship between a number's type and its representation inside a computer. Although most implementations of Scheme will offer at least two different representations of 3, these different representations denote the same integer.

Scheme's numerical operations treat numbers as abstract data, as independent of their representation as possible. Although an implementation of Scheme may use fixnum, flonum, and perhaps other representations for numbers, this should not be apparent to a casual programmer writing simple programs.

It is necessary, however, to distinguish between numbers that are represented exactly and those that may not be. For example, indexes into data structures must be known exactly, as must some polynomial coefficients in a symbolic algebra system. On the other hand, the results of measurements are inherently inexact, and irrational numbers may be approximated by rational and therefore inexact approximations. In order to catch uses of inexact numbers where exact numbers are required, Scheme explicitly distinguishes exact from inexact numbers. This distinction is orthogonal to the dimension of type.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2 Exactness

Scheme numbers are either exact or inexact. A number is exact if it was written as an exact constant or was derived from exact numbers using only exact operations. A number is inexact if it was written as an inexact constant, if it was derived using inexact ingredients, or if it was derived using inexact operations. Thus inexactness is a contagious property of a number.

If two implementations produce exact results for a computation that did not involve inexact intermediate results, the two ultimate results will be mathematically equivalent. This is generally not true of computations involving inexact numbers since approximate methods such as floating point arithmetic may be used, but it is the duty of each implementation to make the result as close as practical to the mathematically ideal result.

Rational operations such as + should always produce exact results when given exact arguments. If the operation is unable to produce an exact result, then it may either report the violation of an implementation restriction or it may silently coerce its result to an inexact value. See section 4.3 Implementation restrictions.

With the exception of inexact->exact, the operations described in this section must generally return inexact results when given any inexact arguments. An operation may, however, return an exact result if it can prove that the value of the result is unaffected by the inexactness of its arguments. For example, multiplication of any number by an exact zero may produce an exact zero result, even if the other argument is inexact.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3 Implementation restrictions

Implementations of Scheme are not required to implement the whole tower of subtypes (see section 4.1 Numerical types), but they must implement a coherent subset consistent with both the purposes of the implementation and the spirit of the Scheme language. For example, an implementation in which all numbers are real may still be quite useful.(1)

Implementations may also support only a limited range of numbers of any type, subject to the requirements of this section. The supported range for exact numbers of any type may be different from the supported range for inexact numbers of that type. For example, an implementation that uses flonums to represent all its inexact real numbers may support a practically unbounded range of exact integers and rationals while limiting the range of inexact reals (and therefore the range of inexact integers and rationals) to the dynamic range of the flonum format. Furthermore the gaps between the representable inexact integers and rationals are likely to be very large in such an implementation as the limits of this range are approached.

An implementation of Scheme must support exact integers throughout the range of numbers that may be used for indexes of lists, vectors, and strings or that may result from computing the length of a list, vector, or string. The length, vector-length, and string-length procedures must return an exact integer, and it is an error to use anything but an exact integer as an index. Furthermore any integer constant within the index range, if expressed by an exact integer syntax, will indeed be read as an exact integer, regardless of any implementation restrictions that may apply outside this range. Finally, the procedures listed below will always return an exact integer result provided all their arguments are exact integers and the mathematically expected result is representable as an exact integer within the implementation:

 
*                gcd                modulo
+                imag-part          numerator
-                inexact->exact     quotient
abs              lcm                rationalize
angle            magnitude          real-part
ceiling          make-polar         remainder
denominator      make-rectangular   round
expt             max                truncate
floor            min

Implementations are encouraged, but not required, to support exact integers and exact rationals of practically unlimited size and precision, and to implement the above procedures and the / procedure in such a way that they always return exact results when given exact arguments. If one of these procedures is unable to deliver an exact result when given exact arguments, then it may either report a violation of an implementation restriction or it may silently coerce its result to an inexact number. Such a coercion may cause an error later.

An implementation may use floating point and other approximate representation strategies for inexact numbers. This report recommends, but does not require, that the IEEE 32-bit and 64-bit floating point standards be followed by implementations that use flonum representations, and that implementations using other representations should match or exceed the precision achievable using these floating point standards.

In particular, implementations that use flonum representations must follow these rules: A flonum result must be represented with at least as much precision as is used to express any of the inexact arguments to that operation. It is desirable (but not required) for potentially inexact operations such as sqrt, when applied to exact arguments, to produce exact answers whenever possible (for example the square root of an exact 4 ought to be an exact 2). If, however, an exact number is operated upon so as to produce an inexact result (as by sqrt), and if the result is represented as a flonum, then the most precise flonum format available must be used; but if the result is represented in some other way then the representation must have at least as much precision as the most precise flonum format available.

Although Scheme allows a variety of written notations for numbers, any particular implementation may support only some of them.(2) For example, an implementation in which all numbers are real need not support the rectangular and polar notations for complex numbers. If an implementation encounters an exact numerical constant that it cannot represent as an exact number, then it may either report a violation of an implementation restriction or it may silently represent the constant by an inexact number.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4 Syntax of numerical constants

A number may be written in binary, octal, decimal, or hexadecimal by the use of a radix prefix. The radix prefixes are #b (binary), #o (octal), #d (decimal), and #x (hexadecimal). With no radix prefix, a number is assumed to be expressed in decimal.

A numerical constant may be specified to be either exact or inexact by a prefix. The prefixes are #e for exact, and #i for inexact. An exactness prefix may appear before or after any radix prefix that is used. If the written representation of a number has no exactness prefix, the constant may be either inexact or exact. It is inexact if it contains a decimal point, an exponent, or a # character in the place of a digit, otherwise it is exact.

In systems with inexact numbers of varying precisions it may be useful to specify the precision of a constant. For this purpose, numerical constants may be written with an exponent marker that indicates the desired precision of the inexact representation. The letters s, f, d, and l specify the use of short, single, double, and long precision, respectively. (When fewer than four internal inexact representations exist, the four size specifications are mapped onto those available. For example, an implementation with two internal representations may map short and single together and long and double together.) In addition, the exponent marker e specifies the default precision for the implementation. The default precision has at least as much precision as double, but implementations may wish to allow this default to be set by the user.

 
3.14159265358979F0
       Round to single --- 3.141593
0.6L0
       Extend to long --- .600000000000000


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5 Numerical operations

See section 1.1.3 Entry Format, for a summary of the naming conventions used to specify restrictions on the types of arguments to numerical routines. The examples used in this section assume that any numerical constant written using an exact notation is indeed represented as an exact number. Some examples also assume that certain numerical constants written using an inexact notation can be represented without loss of accuracy; the inexact constants were chosen so that this is likely to be true in implementations that use flonums to represent inexact numbers.

procedure: number? object
procedure: complex? object
procedure: real? object
procedure: rational? object
procedure: integer? object
These numerical type predicates can be applied to any kind of argument, including non-numbers. They return #t if the object is of the named type, and otherwise they return #f. In general, if a type predicate is true of a number then all higher type predicates are also true of that number. Consequently, if a type predicate is false of a number, then all lower type predicates are also false of that number.(3)

If z is an inexact complex number, then (real? z) is true if and only if (zero? (imag-part z)) is true. If x is an inexact real number, then (integer? x) is true if and only if (= x (round x)).

 
(complex? 3+4i)         =>  #t
(complex? 3)            =>  #t
(real? 3)               =>  #t
(real? -2.5+0.0i)       =>  #t
(real? #e1e10)          =>  #t
(rational? 6/10)        =>  #t
(rational? 6/3)         =>  #t
(integer? 3+0i)         =>  #t
(integer? 3.0)          =>  #t
(integer? 8/4)          =>  #t

Note: The behavior of these type predicates on inexact numbers is unreliable, since any inaccuracy may affect the result.

procedure: exact? z
procedure: inexact? z
These numerical predicates provide tests for the exactness of a quantity. For any Scheme number, precisely one of these predicates is true.

procedure+: exact-integer? object
procedure+: exact-nonnegative-integer? object
procedure+: exact-rational? object
These procedures test for some very common types of numbers. These tests could be written in terms of simpler predicates, but are more efficient.

procedure: = z1 z2 z3 ...
procedure: < x1 x2 x3 ...
procedure: > x1 x2 x3 ...
procedure: <= x1 x2 x3 ...
procedure: >= x1 x2 x3 ...
These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing.

These predicates are transitive. Note that the traditional implementations of these predicates in Lisp-like languages are not transitive.

Note: While it is not an error to compare inexact numbers using these predicates, the results may be unreliable because a small inaccuracy may affect the result; this is especially true of = and zero?. When in doubt, consult a numerical analyst.

procedure: zero? z
procedure: positive? x
procedure: negative? x
procedure: odd? x
procedure: even? x
These numerical predicates test a number for a particular property, returning #t or #f. See note above regarding inexact numbers.

procedure: max x1 x2 ...
procedure: min x1 x2 ...
These procedures return the maximum or minimum of their arguments.

 
(max 3 4)              =>  4    ; exact
(max 3.9 4)            =>  4.0  ; inexact

Note: If any argument is inexact, then the result will also be inexact (unless the procedure can prove that the inaccuracy is not large enough to affect the result, which is possible only in unusual implementations). If min or max is used to compare numbers of mixed exactness, and the numerical value of the result cannot be represented as an inexact number without loss of accuracy, then the procedure may report a violation of an implementation restriction.(4)

procedure: + z1 ...
procedure: * z1 ...
These procedures return the sum or product of their arguments.

 
(+ 3 4)                 =>  7
(+ 3)                   =>  3
(+)                     =>  0
(* 4)                   =>  4
(*)                     =>  1

procedure: - z1 z2 ...
procedure: / z1 z2 ...
With two or more arguments, these procedures return the difference or quotient of their arguments, associating to the left. With one argument, however, they return the additive or multiplicative inverse of their argument.

 
(- 3 4)                 =>  -1
(- 3 4 5)               =>  -6
(- 3)                   =>  -3
(/ 3 4 5)               =>  3/20
(/ 3)                   =>  1/3

procedure+: 1+ z
procedure+: -1+ z
(1+ z) is equivalent to (+ z 1); (-1+ z) is equivalent to (- z 1).

procedure: abs x
abs returns the magnitude of its argument.

 
(abs -7)                =>  7

procedure: quotient n1 n2
procedure: remainder n1 n2
procedure: modulo n1 n2
These procedures implement number-theoretic (integer) division: for positive integers n1 and n2, if n3 and n4 are integers such that

 
n1 = (n2 * n3) + n4

0 <= n4 < n2

then

 
(quotient n1 n2)        =>  n3
(remainder n1 n2)       =>  n4
(modulo n1 n2)          =>  n4

For integers n1 and n2 with n2 not equal to 0,

 
(= n1 
   (+ (* n2 (quotient n1 n2))
      (remainder n1 n2)))
                                    =>  #t

provided all numbers involved in that computation are exact.

The value returned by quotient always has the sign of the product of its arguments. remainder and modulo differ on negative arguments -- the remainder always has the sign of the dividend, the modulo always has the sign of the divisor:

 
(modulo 13 4)           =>  1
(remainder 13 4)        =>  1

(modulo -13 4)          =>  3
(remainder -13 4)       =>  -1

(modulo 13 -4)          =>  -3
(remainder 13 -4)       =>  1

(modulo -13 -4)         =>  -1
(remainder -13 -4)      =>  -1

(remainder -13 -4.0)    =>  -1.0  ; inexact

Note that quotient is the same as integer-truncate.

procedure+: integer-floor n1 n2
procedure+: integer-ceiling n1 n2
procedure+: integer-truncate n1 n2
procedure+: integer-round n1 n2
These procedures combine integer division with rounding. For example, the following are equivalent:

 
(integer-floor n1 n2)
(floor (/ n1 n2))

However, the former is faster and does not produce an intermediate result.

Note that integer-truncate is the same as quotient.

procedure+: integer-divide n1 n2
procedure+: integer-divide-quotient qr
procedure+: integer-divide-remainder qr
integer-divide is equivalent to performing both quotient and remainder at once. The result of integer-divide is an object with two components; the procedures integer-divide-quotient and integer-divide-remainder select those components. These procedures are useful when both the quotient and remainder are needed; often computing both of these numbers simultaneously is much faster than computing them separately.

For example, the following are equivalent:

 
(lambda (n d)
  (cons (quotient n d)
        (remainder n d)))

(lambda (n d)
  (let ((qr (integer-divide n d)))
    (cons (integer-divide-quotient qr)
          (integer-divide-remainder qr))))

procedure: gcd n1 ...
procedure: lcm n1 ...
These procedures return the greatest common divisor or least common multiple of their arguments. The result is always non-negative.

 
(gcd 32 -36)            =>  4
(gcd)                   =>  0

(lcm 32 -36)            =>  288
(lcm 32.0 -36)          =>  288.0  ; inexact
(lcm)                   =>  1

procedure: numerator q
procedure: denominator q
These procedures return the numerator or denominator of their argument; the result is computed as if the argument was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0 is defined to be 1.

 
(numerator (/ 6 4))  =>  3
(denominator (/ 6 4))  =>  2
(denominator (exact->inexact (/ 6 4))) => 2.0

procedure: floor x
procedure: ceiling x
procedure: truncate x
procedure: round x
These procedures return integers. floor returns the largest integer not larger than x. ceiling returns the smallest integer not smaller than x. truncate returns the integer closest to x whose absolute value is not larger than the absolute value of x. round returns the closest integer to x, rounding to even when x is halfway between two integers.

Rationale: round rounds to even for consistency with the rounding modes required by the IEEE floating point standard.

Note: If the argument to one of these procedures is inexact, then the result will also be inexact. If an exact value is needed, the result should be passed to the inexact->exact procedure (or use one of the procedures below).

 
(floor -4.3)          =>  -5.0
(ceiling -4.3)        =>  -4.0
(truncate -4.3)       =>  -4.0
(round -4.3)          =>  -4.0

(floor 3.5)           =>  3.0
(ceiling 3.5)         =>  4.0
(truncate 3.5)        =>  3.0
(round 3.5)           =>  4.0  ; inexact

(round 7/2)           =>  4    ; exact
(round 7)             =>  7

procedure+: floor->exact x
procedure+: ceiling->exact x
procedure+: truncate->exact x
procedure+: round->exact x
These procedures are similar to the preceding procedures except that they always return an exact result. For example, the following are equivalent

 
(floor->exact x)
(inexact->exact (floor x))

except that the former is faster and has fewer range restrictions.

procedure: rationalize x y
procedure+: rationalize->exact x y
rationalize returns the simplest rational number differing from x by no more than y. A rational number r1 is simpler than another rational number r2 if r1=p1/q1 and r2=p2/q2 (both in lowest terms) and |p1|<=|p2| and |q1|<=|q2|. Thus 3/5 is simpler than 4/7. Although not all rationals are comparable in this ordering (consider 2/7 and 3/5) any interval contains a rational number that is simpler than every other rational number in that interval (the simpler 2/5 lies between 2/7 and 3/5). Note that 0=0/1 is the simplest rational of all.

 
(rationalize (inexact->exact .3) 1/10)  => 1/3    ; exact
(rationalize .3 1/10)                   => #i1/3  ; inexact

rationalize->exact is similar to rationalize except that it always returns an exact result.

procedure+: simplest-rational x y
procedure+: simplest-exact-rational x y
simplest-rational returns the simplest rational number between x and y inclusive; simplest-exact-rational is similar except that it always returns an exact result.

These procedures implement the same functionality as rationalize and rationalize->exact, except that they specify the input range by its endpoints; rationalize specifies the range by its center point and its (half-) width.

procedure: exp z
procedure: log z
procedure: sin z
procedure: cos z
procedure: tan z
procedure: asin z
procedure: acos z
procedure: atan z
procedure: atan y x
These procedures compute the usual transcendental functions. log computes the natural logarithm of z (not the base ten logarithm). asin, acos, and atan compute arcsine, arccosine, and arctangent, respectively. The two-argument variant of atan computes (angle (make-rectangular x y)) (see below).

In general, the mathematical functions log, arcsine, arccosine, and arctangent are multiply defined. For nonzero real x, the value of log x is defined to be the one whose imaginary part lies in the range minus pi (exclusive) to pi (inclusive). log 0 is undefined. The value of log z when z is complex is defined according to the formula

 
log z = log magnitude(z) + i angle(z)

With log defined this way, the values of arcsine, arccosine, and arctangent are according to the following formulae:

 
arcsin(z) = -i log(i z + sqrt(1 - z^2))
arccos(z) = pi/2 - arcsin(z)
arctan(z) = (log(1 + i z) + log(1 - i z)) / (2 i)

The above specification follows Common Lisp: the Language, which in turn cites Principal Values and Branch Cuts in Complex APL; refer to these sources for more detailed discussion of branch cuts, boundary conditions, and implementation of these functions. When it is possible these procedures produce a real result from a real argument.

procedure: sqrt z
Returns the principal square root of z. The result will have either positive real part, or zero real part and non-negative imaginary part.

procedure: expt z1 z2
Returns z1 raised to the power z2:

 
z1^z2 = e^(z2 log z1)

0^0 is defined to be equal to 1.

procedure: make-rectangular x1 x2
procedure: make-polar x3 x4
procedure: real-part z
procedure: imag-part z
procedure: magnitude z
procedure: angle z
procedure+: conjugate z
Suppose x1, x2, x3, and x4 are real numbers and z is a complex number such that

 
z = x1 + x2 i = x3 e^(i x4)

Then make-rectangular and make-polar return z, real-part returns x1, imag-part returns x2, magnitude returns x3, and angle returns x4. In the case of angle, whose value is not uniquely determined by the preceding rule, the value returned will be the one in the range minus pi (exclusive) to pi (inclusive).

conjugate returns the complex conjugate of z.

procedure: exact->inexact z
procedure: inexact->exact z
exact->inexact returns an inexact representation of z. The value returned is the inexact number that is numerically closest to the argument. If an exact argument has no reasonably close inexact equivalent, then a violation of an implementation restriction may be reported; MIT Scheme signals an error of type condition-type:bad-range-argument in this case.

inexact->exact returns an exact representation of z. The value returned is the exact number that is numerically closest to the argument. If an inexact argument has no reasonably close exact equivalent, then a violation of an implementation restriction may be reported; in MIT Scheme this case does not occur because all inexact numbers are representable as exact numbers.

These procedures implement the natural one-to-one correspondence between exact and inexact integers throughout an implementation-dependent range. See section 4.3 Implementation restrictions.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6 Numerical input and output

procedure: number->string number [radix]
Radix must be an exact integer, either 2, 8, 10, or 16. If omitted, radix defaults to 10. The procedure number->string takes a number and a radix and returns as a string an external representation of the given number in the given radix such that

 
(let ((number number)
      (radix radix))
  (eqv? number
        (string->number (number->string number radix)
                        radix)))

is true. It is an error if no possible result makes this expression true.

If number is inexact, the radix is 10, and the above expression can be satisfied by a result that contains a decimal point, then the result contains a decimal point and is expressed using the minimum number of digits (exclusive of exponent and trailing zeroes) needed to make the above expression true; otherwise the format of the result is unspecified.

The result returned by number->string never contains an explicit radix prefix.

Note: The error case can occur only when number is not a complex number or is a complex number with an non-rational real or imaginary part.

Rationale: If number is an inexact number represented using flonums, and the radix is 10, then the above expression is normally satisfied by a result containing a decimal point. The unspecified case allows for infinities, NaNs, and non-flonum representations.

variable+: flonum-parser-fast?
This variable controls the behavior of string->number when parsing inexact numbers. Specifically, it allows the user to trade off accuracy against speed.

When set to its default value, #f, the parser provides maximal accuracy, as required by the Scheme standard. If set to #t, the parser uses faster algorithms that will sometimes introduce small errors in the result. The errors affect a few of the least-significant bits of the result, and consequently can be tolerated by many applications.

variable+: flonum-unparser-cutoff
This variable controls the action of number->string when number is a flonum (and consequently controls all printing of flonums). The value of this variable is normally a list of three items:

rounding-type
One of the following symbols: normal, relative, or absolute. The symbol normal means that the number should be printed with full precision. The symbol relative means that the number should be rounded to a specific number of digits. The symbol absolute means that the number should be rounded so that there are a specific number of digits to the right of the decimal point.

precision
An exact integer. If rounding-type is normal, precision is ignored. If rounding-type is relative, precision must be positive, and it specifies the number of digits to which the printed representation will be rounded. If rounding-type is absolute, the printed representation will be rounded precision digits to the right of the decimal point; if precision is negative, the representation is rounded (- precision) digits to the left of the decimal point.

format-type
One of the symbols: normal, scientific, or engineering. This specifies the format in which the number will be printed.
scientific specifies that the number will be printed using scientific notation: x.xxxeyyy. In other words, the number is printed as a mantissa between zero inclusive and ten exclusive, and an exponent. engineering is like scientific, except that the exponent is always a power of three, and the mantissa is constrained to be between zero inclusive and 1000 exclusive. If normal is specified, the number will be printed in positional notation if it is "small enough", otherwise it is printed in scientific notation. A number is "small enough" when the number of digits that would be printed using positional notation does not exceed the number of digits of precision in the underlying floating-point number representation; IEEE double-precision floating-point numbers have 17 digits of precision.

This three-element list may be abbreviated in two ways. First, the symbol normal may be used, which is equivalent to the list (normal 0 normal). Second, the third element of the list, format-type, may be omitted, in which case it defaults to normal.

The default value for flonum-unparser-cutoff is normal. If it is bound to a value different from those described here, number->string issues a warning and acts as though the value had been normal.

Some examples of flonum-unparser-cutoff:

 
(number->string (* 4 (atan 1 1)))
                                    => "3.141592653589793"
(fluid-let ((flonum-unparser-cutoff '(relative 5)))
  (number->string (* 4 (atan 1 1))))
                                    => "3.1416"
(fluid-let ((flonum-unparser-cutoff '(relative 5)))
  (number->string (* 4000 (atan 1 1))))
                                    => "3141.6"
(fluid-let ((flonum-unparser-cutoff '(relative 5 scientific)))
  (number->string (* 4000 (atan 1 1))))
                                    => "3.1416e3"
(fluid-let ((flonum-unparser-cutoff '(relative 5 scientific)))
  (number->string (* 40000 (atan 1 1))))
                                    => "3.1416e4"
(fluid-let ((flonum-unparser-cutoff '(relative 5 engineering)))
  (number->string (* 40000 (atan 1 1))))
                                    => "31.416e3"
(fluid-let ((flonum-unparser-cutoff '(absolute 5)))
  (number->string (* 4 (atan 1 1))))
                                    => "3.14159"
(fluid-let ((flonum-unparser-cutoff '(absolute 5)))
  (number->string (* 4000 (atan 1 1))))
                                    => "3141.59265"
(fluid-let ((flonum-unparser-cutoff '(absolute -4)))
  (number->string (* 4e10 (atan 1 1))))
                                    => "31415930000."
(fluid-let ((flonum-unparser-cutoff '(absolute -4 scientific)))
  (number->string (* 4e10 (atan 1 1))))
                                    => "3.141593e10"
(fluid-let ((flonum-unparser-cutoff '(absolute -4 engineering)))
  (number->string (* 4e10 (atan 1 1))))
                                    => "31.41593e9"
(fluid-let ((flonum-unparser-cutoff '(absolute -5)))
  (number->string (* 4e10 (atan 1 1))))
                                    => "31415900000."

procedure: string->number string [radix]
Returns a number of the maximally precise representation expressed by the given string. Radix must be an exact integer, either 2, 8, 10, or 16. If supplied, radix is a default radix that may be overridden by an explicit radix prefix in string (e.g. "#o177"). If radix is not supplied, then the default radix is 10. If string is not a syntactically valid notation for a number, then string->number returns #f.

 
(string->number "100")        =>  100
(string->number "100" 16)     =>  256
(string->number "1e2")        =>  100.0
(string->number "15##")       =>  1500.0

Note that a numeric representation using a decimal point or an exponent marker is not recognized unless radix is 10.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7 Fixnum and Flonum Operations

This section describes numerical operations that are restricted forms of the operations described above. These operations are useful because they compile very efficiently. However, care should be exercised: if used improperly, these operations can return incorrect answers, or even malformed objects that confuse the garbage collector.

4.7.1 Fixnum Operations  
4.7.2 Flonum Operations  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7.1 Fixnum Operations

A fixnum is an exact integer that is small enough to fit in a machine word. In MIT Scheme, fixnums are typically 24 or 26 bits, depending on the machine; it is reasonable to assume that fixnums are at least 24 bits. Fixnums are signed; they are encoded using 2's complement.

All exact integers that are small enough to be encoded as fixnums are always encoded as fixnums -- in other words, any exact integer that is not a fixnum is too big to be encoded as such. For this reason, small constants such as 0 or 1 are guaranteed to be fixnums.

procedure+: fix:fixnum? object
Returns #t if object is a fixnum; otherwise returns #f.

Here is an expression that determines the largest fixnum:

 
(let loop ((n 1))
  (if (fix:fixnum? n)
      (loop (* n 2))
      (- n 1)))

A similar expression determines the smallest fixnum.

procedure+: fix:= fixnum fixnum
procedure+: fix:< fixnum fixnum
procedure+: fix:> fixnum fixnum
procedure+: fix:<= fixnum fixnum
procedure+: fix:>= fixnum fixnum
These are the standard order and equality predicates on fixnums. When compiled, they do not check the types of their arguments.

procedure+: fix:zero? fixnum
procedure+: fix:positive? fixnum
procedure+: fix:negative? fixnum
These procedures compare their argument to zero. When compiled, they do not check the type of their argument. The code produced by the following expressions is identical:

 
(fix:zero? fixnum)
(fix:= fixnum 0)

Similarly, fix:positive? and fix:negative? produce code identical to equivalent expressions using fix:> and fix:<.

procedure+: fix:+ fixnum fixnum
procedure+: fix:- fixnum fixnum
procedure+: fix:* fixnum fixnum
procedure+: fix:quotient fixnum fixnum
procedure+: fix:remainder fixnum fixnum
procedure+: fix:gcd fixnum fixnum
procedure+: fix:1+ fixnum
procedure+: fix:-1+ fixnum
These procedures are the standard arithmetic operations on fixnums. When compiled, they do not check the types of their arguments. Furthermore, they do not check to see if the result can be encoded as a fixnum. If the result is too large to be encoded as a fixnum, a malformed object is returned, with potentially disastrous effect on the garbage collector.

procedure+: fix:divide fixnum fixnum
This procedure is like integer-divide, except that its arguments and its results must be fixnums. It should be used in conjunction with integer-divide-quotient and integer-divide-remainder.

The following are bitwise-logical operations on fixnums.

procedure+: fix:not fixnum
This returns the bitwise-logical inverse of its argument. When compiled, it does not check the type of its argument.

 
(fix:not 0)                             =>  -1
(fix:not -1)                            =>  0
(fix:not 1)                             =>  -2
(fix:not -34)                           =>  33

procedure+: fix:and fixnum fixnum
This returns the bitwise-logical "and" of its arguments. When compiled, it does not check the types of its arguments.

 
(fix:and #x43 #x0f)                     =>  3
(fix:and #x43 #xf0)                     =>  #x40

procedure+: fix:andc fixnum fixnum
Returns the bitwise-logical "and" of the first argument with the bitwise-logical inverse of the second argument. When compiled, it does not check the types of its arguments.

 
(fix:andc #x43 #x0f)                    =>  #x40
(fix:andc #x43 #xf0)                    =>  3

procedure+: fix:or fixnum fixnum
This returns the bitwise-logical "inclusive or" of its arguments. When compiled, it does not check the types of its arguments.

 
(fix:or #x40 3)                         => #x43
(fix:or #x41 3)                         => #x43

procedure+: fix:xor fixnum fixnum
This returns the bitwise-logical "exclusive or" of its arguments. When compiled, it does not check the types of its arguments.

 
(fix:xor #x40 3)                        => #x43
(fix:xor #x41 3)                        => #x42

procedure+: fix:lsh fixnum1 fixnum2
This procedure returns the result of logically shifting fixnum1 by fixnum2 bits. If fixnum2 is positive, fixnum1 is shifted left; if negative, it is shifted right. When compiled, it does not check the types of its arguments, nor the validity of its result.

 
(fix:lsh 1 10)                          =>  #x400
(fix:lsh #x432 -10)                     =>  1
(fix:lsh -1 3)                          =>  -8
(fix:lsh -128 -4)                       =>  #x3FFFF8


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7.2 Flonum Operations

A flonum is an inexact real number that is implemented as a floating-point number. In MIT Scheme, all inexact real numbers are flonums. For this reason, constants such as 0. and 2.3 are guaranteed to be flonums.

procedure+: flo:flonum? object
Returns #t if object is a flonum; otherwise returns #f.

procedure+: flo:= flonum1 flonum2
procedure+: flo:< flonum1 flonum2
procedure+: flo:> flonum1 flonum2
These procedures are the standard order and equality predicates on flonums. When compiled, they do not check the types of their arguments.

procedure+: flo:zero? flonum
procedure+: flo:positive? flonum
procedure+: flo:negative? flonum
Each of these procedures compares its argument to zero. When compiled, they do not check the type of their argument.

procedure+: flo:+ flonum1 flonum2
procedure+: flo:- flonum1 flonum2
procedure+: flo:* flonum1 flonum2
procedure+: flo:/ flonum1 flonum2
These procedures are the standard arithmetic operations on flonums. When compiled, they do not check the types of their arguments.

procedure+: flo:negate flonum
This procedure returns the negation of its argument. When compiled, it does not check the type of its argument. Equivalent to (flo:- 0. flonum).

procedure+: flo:abs flonum
procedure+: flo:exp flonum
procedure+: flo:log flonum
procedure+: flo:sin flonum
procedure+: flo:cos flonum
procedure+: flo:tan flonum
procedure+: flo:asin flonum
procedure+: flo:acos flonum
procedure+: flo:atan flonum
procedure+: flo:sqrt flonum
procedure+: flo:expt flonum1 flonum2
procedure+: flo:floor flonum
procedure+: flo:ceiling flonum
procedure+: flo:truncate flonum
procedure+: flo:round flonum
procedure+: flo:floor->exact flonum
procedure+: flo:ceiling->exact flonum
procedure+: flo:truncate->exact flonum
procedure+: flo:round->exact flonum
These procedures are flonum versions of the corresponding procedures. When compiled, they do not check the types of their arguments.

procedure+: flo:atan2 flonum1 flonum2
This is the flonum version of atan with two arguments. When compiled, it does not check the types of its arguments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8 Random Numbers

MIT Scheme provides a facility for generating pseudo-random numbers. The current implementation is a "subtract-with-carry" random-number generator, based on the algorithm from A New Class of Random Number Generators, George Marsaglia and Arif Zaman, The Annals of Applied Probability, Vol. 1, No. 3, 1991. At the time it was implemented, this was a good algorithm for general purposes, but the state of the art in random-number generation is constantly changing. If necessary, the implementation will be updated to use a new algorithm while retaining the same interface.

The interface described here is very similar to that of Common Lisp.

procedure+: random modulus [state]
Modulus must be a positive real number. random returns a pseudo-random number between zero (inclusive) and modulus (exclusive). The exactness of the returned number is the same as the exactness of modulus. Additionally, if modulus is an exact integer, the returned number will be also. Usually, modulus is either an exact integer or an inexact real; the current implementation has been tuned to make these two cases fast.

If state is given and not #f, it must be a random-state object; otherwise, it defaults to the value of the variable *random-state*. This object is used to maintain the state of the pseudo-random-number generator and is altered as a side effect of the random procedure.

 
(random 1.0)    => .32744744667719056
(random 1.0)    => .01668326768172354
(random 10)     => 3
(random 10)     => 8
(random 100)    => 38
(random 100)    => 63
(random 100/3)  => 130501475769920525/6755399441055744
(random 100/3)  => 170571694016427575/13510798882111488

procedure+: flo:random-unit state
State must be a random-state object. flo:random-unit returns a pseudo-random number between zero inclusive and one exclusive; the returned number is always a flonum and therefore an inexact real number. flo:random-unit is equivalent to random with a modulus of 1.0, except that it is faster.

The next three definitions concern random-state objects. In addition to these definitions, it is important to know that random-state objects are specifically designed so that they can be saved to disk using the fasdump procedure, and later restored using the fasload procedure. This allows a particular random-state object to be saved in order to replay a particular pseudo-random sequence.

variable+: *random-state*
This variable holds a data structure, a random-state object, that encodes the internal state of the random-number generator that random uses by default. A call to random will perform a side effect on this data structure. This variable may be changed, using set! or fluid-let, to hold a new random-state object.

procedure+: make-random-state [state]
This procedure returns a new random-state object, suitable for use as the value of the variable *random-state*, or as the state argument to random. If state is not given or #f, make-random-state returns a copy of the current random-number state object (the value of the variable *random-state*). If state is a random-state object, a copy of that object is returned. If state is #t, then a new random-state object is returned that has been "randomly" initialized by some means (such as by a time-of-day clock).

procedure+: random-state? object
Returns #t if object is a random-state object, otherwise returns #f.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Chris Hanson on July, 18 2001 using texi2html