4.27.2.4 IEEE 754 floating point arithmetic
The Prolog ISO standard defines that floating point arithmetic
returns a valid floating point number or raises an exception. IEEE
floating point arithmetic defines two modes: raising exceptions and
propagating the special float values NaN
, Inf
, -Inf
and
-0.0
. SWI-Prolog implements a part of the
ECLiPSe
proposal to support non-exception based processing of floating point
numbers. There are four flags that define handling the four exceptional
events in floating point arithmetic, providing the choice between
error
and returning the IEEE special value. Note that these
flags only apply for floating point arithmetic. For example
rational division by zero always raises an exception.
Flag | Default | Alternative |
float_overflow | error | infinity |
float_zero_div | error | infinity |
float_undefined | error | nan |
float_underflow | ignore | error |
The Prolog flag float_rounding
and the function
roundtoward/2
control the rounding mode for floating point arithmetic. The default
rounding is to_nearest
and the following alternatives are
provided: to_positive
, to_negative
and
to_zero
.
- [det]float_class(+Float, -Class)
- Wraps C99 fpclassify() to access the class of a floating point
number. Raises a type error if Float is not a float. Defined
classes are below.
- nan
- Float is “Not a number” . See nan/0.
May be produced if the Prolog flag float_undefined
is set to
nan
. Although IEEE 754 allows NaN to carry a payload and have a sign, SWI-Prolog has only a single NaN values. Note that two NaN terms compare equal in the standard order of terms (==/2, etc.), they compare non-equal for arithmetic (=:=/2, etc.). - infinite
- Float is positive or negative infinity. See inf/0.
May be produced if the Prolog flag float_overflow
or the flag float_zero_div
is set to
infinity
. - zero
- Float is zero (0.0 or -0.0)
- subnormal
- Float is too small to be represented in normalized format.
May not be produced if the Prolog flag
float_underflow
is set to
error
. - normal
- Float is a normal floating point number.
- [det]float_parts(+Float, -Mantissa, -Base, -Exponent)
- True when Mantissa is the normalized fraction of Float,
Base is the radix and Exponent is the
exponent. This uses the C function frexp(). If Float
is NaN or ±Inf
Mantissa has the same value and Exponent is 0
(zero). In the current implementation Base is always 2. The
following relation is always true:
Float =:= Mantissa × Base^Exponent
- [det]bounded_number(?Low, ?High, +Num)
- True if Low < Num < High. Raises
a type error if Num is not a number. This predicate can be
used both to check and generate bounds across the various numeric types.
Note that a number cannot be bounded by itself and
NaN
,Inf
, and-Inf
are not bounded numbers.If Low and/or High are variables they will be unified with tightest values that still meet the bounds criteria. The generated bounds will be integers if Num is an integer; otherwise they will be floats (also see nexttoward/2 for generating float bounds). Some examples:
?- bounded_number(0,10,1). true. ?- bounded_number(0.0,1.0,1r2). true. ?- bounded_number(L,H,1.0). L = 0.9999999999999999, H = 1.0000000000000002. ?- bounded_number(L,H,-1). L = -2, H = 0. ?- bounded_number(0,1r2,1). false. ?- bounded_number(L,H,1.0Inf). false.