mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Infinities and NaNs are no longer rational
* libguile/numbers.c (scm_rational_p): Return #f for infinities and NaNs, per R6RS. Previously it returned #t for real infinities and NaNs. They are still considered real by scm_real `real?' however, per R6RS. Also simplify the code. (scm_real_p): New implementation to reflect the fact that the rationals and reals are no longer the same set. Previously it just called scm_rational_p. (scm_integer_p): Simplify the code. * test-suite/tests/numbers.test: Add test cases for `rational?' and `real?' applied to infinities and NaNs. * doc/ref/api-data.texi (Real and Rational Numbers): Update docs to reflect the fact that infinities and NaNs are no longer rational, and that `real?' no longer implies `rational?'. Improve discussion of infinities and NaNs. * NEWS: Add NEWS entries, and combine with an earlier entry about infinities no longer being integers.
This commit is contained in:
parent
2e6e1933b4
commit
c960e55600
4 changed files with 74 additions and 65 deletions
18
NEWS
18
NEWS
|
@ -27,11 +27,6 @@ Previously, `(equal? +nan.0 +nan.0)' returned #f, although
|
|||
both returned #t. R5RS requires that `equal?' behave like
|
||||
`eqv?' when comparing numbers.
|
||||
|
||||
*** Infinities are no longer integers.
|
||||
|
||||
Following the R6RS, infinities (+inf.0 and -inf.0) are no longer
|
||||
considered to be integers.
|
||||
|
||||
*** `expt' and `integer-expt' changes when the base is 0
|
||||
|
||||
While `(expt 0 0)' is still 1, and `(expt 0 N)' for N > 0 is still
|
||||
|
@ -40,6 +35,19 @@ integer-expt. This is more correct, and conforming to R6RS, but seems
|
|||
to be incompatible with R5RS, which would return 0 for all non-zero
|
||||
values of N.
|
||||
|
||||
*** Infinities are no longer integers, nor rationals
|
||||
|
||||
scm_integer_p `integer?' and scm_rational_p `rational?' now return #f
|
||||
for infinities, per R6RS. Previously they returned #t for real
|
||||
infinities. The real infinities and NaNs are still considered real by
|
||||
scm_real `real?' however, per R6RS.
|
||||
|
||||
*** NaNs are no longer rationals
|
||||
|
||||
scm_rational_p `rational?' now returns #f for NaN values, per R6RS.
|
||||
Previously it returned #t for real NaN values. They are still
|
||||
considered real by scm_real `real?' however, per R6RS.
|
||||
|
||||
*** `inf?' and `nan?' now throw exceptions for non-reals
|
||||
|
||||
The domain of `inf?' and `nan?' is the real numbers. Guile now signals
|
||||
|
|
|
@ -492,10 +492,10 @@ are not rational, for example @m{\sqrt2, the square root of 2}, and
|
|||
@m{\pi,pi}.
|
||||
|
||||
Guile can represent both exact and inexact rational numbers, but it
|
||||
can not represent irrational numbers. Exact rationals are represented
|
||||
by storing the numerator and denominator as two exact integers.
|
||||
Inexact rationals are stored as floating point numbers using the C
|
||||
type @code{double}.
|
||||
cannot represent precise finite irrational numbers. Exact rationals are
|
||||
represented by storing the numerator and denominator as two exact
|
||||
integers. Inexact rationals are stored as floating point numbers using
|
||||
the C type @code{double}.
|
||||
|
||||
Exact rationals are written as a fraction of integers. There must be
|
||||
no whitespace around the slash:
|
||||
|
@ -518,26 +518,41 @@ example:
|
|||
4.0
|
||||
@end lisp
|
||||
|
||||
The limited precision of Guile's encoding means that any ``real'' number
|
||||
in Guile can be written in a rational form, by multiplying and then dividing
|
||||
by sufficient powers of 10 (or in fact, 2). For example,
|
||||
@samp{-0.00000142857931198} is the same as @minus{}142857931198 divided by
|
||||
100000000000000000. In Guile's current incarnation, therefore, the
|
||||
@code{rational?} and @code{real?} predicates are equivalent.
|
||||
The limited precision of Guile's encoding means that any finite ``real''
|
||||
number in Guile can be written in a rational form, by multiplying and
|
||||
then dividing by sufficient powers of 10 (or in fact, 2). For example,
|
||||
@samp{-0.00000142857931198} is the same as @minus{}142857931198 divided
|
||||
by 100000000000000000. In Guile's current incarnation, therefore, the
|
||||
@code{rational?} and @code{real?} predicates are equivalent for finite
|
||||
numbers.
|
||||
|
||||
|
||||
Dividing by an exact zero leads to a error message, as one might
|
||||
expect. However, dividing by an inexact zero does not produce an
|
||||
error. Instead, the result of the division is either plus or minus
|
||||
infinity, depending on the sign of the divided number.
|
||||
Dividing by an exact zero leads to a error message, as one might expect.
|
||||
However, dividing by an inexact zero does not produce an error.
|
||||
Instead, the result of the division is either plus or minus infinity,
|
||||
depending on the sign of the divided number and the sign of the zero
|
||||
divisor (some platforms support signed zeroes @samp{-0.0} and
|
||||
@samp{+0.0}; @samp{0.0} is the same as @samp{+0.0}).
|
||||
|
||||
The infinities are written @samp{+inf.0} and @samp{-inf.0},
|
||||
respectively. This syntax is also recognized by @code{read} as an
|
||||
extension to the usual Scheme syntax. The infinities are considered to
|
||||
be inexact, non-integer values.
|
||||
Dividing zero by an inexact zero yields a @acronym{NaN} (`not a number')
|
||||
value, although they are actually considered numbers by Scheme.
|
||||
Attempts to compare a @acronym{NaN} value with any number (including
|
||||
itself) using @code{=}, @code{<}, @code{>}, @code{<=} or @code{>=}
|
||||
always returns @code{#f}. Although a @acronym{NaN} value is not
|
||||
@code{=} to itself, it is both @code{eqv?} and @code{equal?} to itself
|
||||
and other @acronym{NaN} values. However, the preferred way to test for
|
||||
them is by using @code{nan?}.
|
||||
|
||||
Dividing zero by zero yields something that is not a number at all:
|
||||
@samp{+nan.0}. This is the special `not a number' value.
|
||||
The real @acronym{NaN} values and infinities are written @samp{+nan.0},
|
||||
@samp{+inf.0} and @samp{-inf.0}. This syntax is also recognized by
|
||||
@code{read} as an extension to the usual Scheme syntax. These special
|
||||
values are considered by Scheme to be inexact real numbers but not
|
||||
rational. Note that non-real complex numbers may also contain
|
||||
infinities or @acronym{NaN} values in their real or imaginary parts. To
|
||||
test a real number to see if it is infinite, a @acronym{NaN} value, or
|
||||
neither, use @code{inf?}, @code{nan?}, or @code{finite?}, respectively.
|
||||
Every real number in Scheme belongs to precisely one of those three
|
||||
classes.
|
||||
|
||||
On platforms that follow @acronym{IEEE} 754 for their floating point
|
||||
arithmetic, the @samp{+inf.0}, @samp{-inf.0}, and @samp{+nan.0} values
|
||||
|
@ -545,13 +560,6 @@ are implemented using the corresponding @acronym{IEEE} 754 values.
|
|||
They behave in arithmetic operations like @acronym{IEEE} 754 describes
|
||||
it, i.e., @code{(= +nan.0 +nan.0)} @result{} @code{#f}.
|
||||
|
||||
While @samp{+nan.0} is not @code{=} to itself, it is @code{eqv?} to
|
||||
itself.
|
||||
|
||||
To test for the special values, use the functions @code{inf?} and
|
||||
@code{nan?}. To test for numbers than are neither infinite nor a NaN,
|
||||
use @code{finite?}.
|
||||
|
||||
@deffn {Scheme Procedure} real? obj
|
||||
@deffnx {C Function} scm_real_p (obj)
|
||||
Return @code{#t} if @var{obj} is a real number, else @code{#f}. Note
|
||||
|
@ -566,9 +574,6 @@ Return @code{#t} if @var{x} is a rational number, @code{#f} otherwise.
|
|||
Note that the set of integer values forms a subset of the set of
|
||||
rational numbers, i. e. the predicate will also be fulfilled if
|
||||
@var{x} is an integer number.
|
||||
|
||||
Since Guile can not represent irrational numbers, every number
|
||||
satisfying @code{real?} also satisfies @code{rational?} in Guile.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} rationalize x eps
|
||||
|
@ -607,12 +612,12 @@ NaN, @code{#f} otherwise.
|
|||
|
||||
@deffn {Scheme Procedure} nan
|
||||
@deffnx {C Function} scm_nan ()
|
||||
Return NaN.
|
||||
Return @samp{+nan.0}, a @acronym{NaN} value.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} inf
|
||||
@deffnx {C Function} scm_inf ()
|
||||
Return Inf.
|
||||
Return @samp{+inf.0}, positive infinity.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} numerator x
|
||||
|
|
|
@ -3281,8 +3281,8 @@ SCM_DEFINE (scm_real_p, "real?", 1, 0, 0,
|
|||
"fulfilled if @var{x} is an integer number.")
|
||||
#define FUNC_NAME s_scm_real_p
|
||||
{
|
||||
/* we can't represent irrational numbers. */
|
||||
return scm_rational_p (x);
|
||||
return scm_from_bool
|
||||
(SCM_I_INUMP (x) || SCM_REALP (x) || SCM_BIGP (x) || SCM_FRACTIONP (x));
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
@ -3294,18 +3294,12 @@ SCM_DEFINE (scm_rational_p, "rational?", 1, 0, 0,
|
|||
"fulfilled if @var{x} is an integer number.")
|
||||
#define FUNC_NAME s_scm_rational_p
|
||||
{
|
||||
if (SCM_I_INUMP (x))
|
||||
return SCM_BOOL_T;
|
||||
else if (SCM_IMP (x))
|
||||
return SCM_BOOL_F;
|
||||
else if (SCM_BIGP (x))
|
||||
return SCM_BOOL_T;
|
||||
else if (SCM_FRACTIONP (x))
|
||||
if (SCM_I_INUMP (x) || SCM_BIGP (x) || SCM_FRACTIONP (x))
|
||||
return SCM_BOOL_T;
|
||||
else if (SCM_REALP (x))
|
||||
/* due to their limited precision, all floating point numbers are
|
||||
rational as well. */
|
||||
return SCM_BOOL_T;
|
||||
/* due to their limited precision, finite floating point numbers are
|
||||
rational as well. (finite means neither infinity nor a NaN) */
|
||||
return scm_from_bool (DOUBLE_IS_FINITE (SCM_REAL_VALUE (x)));
|
||||
else
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
|
@ -3317,23 +3311,15 @@ SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
|
|||
"else.")
|
||||
#define FUNC_NAME s_scm_integer_p
|
||||
{
|
||||
double r;
|
||||
if (SCM_I_INUMP (x))
|
||||
if (SCM_I_INUMP (x) || SCM_BIGP (x))
|
||||
return SCM_BOOL_T;
|
||||
if (SCM_IMP (x))
|
||||
else if (SCM_REALP (x))
|
||||
{
|
||||
double val = SCM_REAL_VALUE (x);
|
||||
return scm_from_bool (!isinf (val) && (val == floor (val)));
|
||||
}
|
||||
else
|
||||
return SCM_BOOL_F;
|
||||
if (SCM_BIGP (x))
|
||||
return SCM_BOOL_T;
|
||||
if (!SCM_INEXACTP (x))
|
||||
return SCM_BOOL_F;
|
||||
if (SCM_COMPLEXP (x))
|
||||
return SCM_BOOL_F;
|
||||
r = SCM_REAL_VALUE (x);
|
||||
if (isinf (r))
|
||||
return SCM_BOOL_F;
|
||||
if (r == floor (r))
|
||||
return SCM_BOOL_T;
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
|
@ -1505,6 +1505,11 @@
|
|||
(pass-if (real? (+ 1 fixnum-max)))
|
||||
(pass-if (real? (- 1 fixnum-min)))
|
||||
(pass-if (real? 1.3))
|
||||
(pass-if (real? +inf.0))
|
||||
(pass-if (real? -inf.0))
|
||||
(pass-if (real? +nan.0))
|
||||
(pass-if (not (real? +inf.0-inf.0i)))
|
||||
(pass-if (not (real? +nan.0+nan.0i)))
|
||||
(pass-if (not (real? 3+4i)))
|
||||
(pass-if (not (real? #\a)))
|
||||
(pass-if (not (real? "a")))
|
||||
|
@ -1515,7 +1520,7 @@
|
|||
(pass-if (not (real? (current-input-port)))))
|
||||
|
||||
;;;
|
||||
;;; rational? (same as real? right now)
|
||||
;;; rational?
|
||||
;;;
|
||||
|
||||
(with-test-prefix "rational?"
|
||||
|
@ -1526,6 +1531,11 @@
|
|||
(pass-if (rational? (+ 1 fixnum-max)))
|
||||
(pass-if (rational? (- 1 fixnum-min)))
|
||||
(pass-if (rational? 1.3))
|
||||
(pass-if (not (rational? +inf.0)))
|
||||
(pass-if (not (rational? -inf.0)))
|
||||
(pass-if (not (rational? +nan.0)))
|
||||
(pass-if (not (rational? +inf.0-inf.0i)))
|
||||
(pass-if (not (rational? +nan.0+nan.0i)))
|
||||
(pass-if (not (rational? 3+4i)))
|
||||
(pass-if (not (rational? #\a)))
|
||||
(pass-if (not (rational? "a")))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue