# IEEE-754 Floating point support The ISO standard for floating point arithmetic does not specify any properties about the floating point representation and demands the result of an arithmetic operation to be either a _normal_ float or an exception (float_overflow or evaluation_error). This makes a lot of sense as it avoids many of the complications handling _non-normal_ floats. On the other hand, The [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754) was estabished in 1985 and the support for floating point numbers in most programming languages is based on this standard. ECLiPSe has created a proposal to include IEEE 754 based arithmetic [in Prolog](http://eclipseclp.org/Specs/core_update_float.html) This notebook expains support for IEEE 754 in SWI-Prolog. Currently, Prolog flags comforming the ECliPSe proposal to choose between exceptions and returning _special_ floats and some support for rounding has been implemented in SWI-Prolog 8.1.22. Consistent handling of special values throughoput the system is not yet implemented. As most of the arithmetic eventually relies on C99 float processing, many of the functions do comply.
## Underflows ISO Prolog defines no special handling for _subnormal_ floats, which are floats that are so small that their value becomes imprecise. In the program below we divide `1` _N_ times by `10.0` and then multiply back. This immediately results in a small error because IEEE 754 _binary_ floats cannot precisely represent decimal fractions. Close to the smallest float the difference is getting large and with over `324` iterations the result is simply zero. The predicate float_class/2 can be used to test that a float is critically close to the smallest representable number and therefore imprecise. The flag `float_underflow` can be used to make this invalid computation raise an exception as illustrated by the third query.
I = 10, u(I, 1, X), o(I, X, Y).
I = 323, u(I, 1, X), o(I, X, Y), float_class(X, Class).
I = 323, set_prolog_flag(float_underflow, error), u(I, 1, X), o(I, X, Y), float_class(X, Class).
u(0, X, X) :- !. u(N, X, Y) :- X1 is X/10.0, N1 is N-1, u(N1, X1, Y). o(0, X, X) :- !. o(N, X, Y) :- X1 is X*10.0, N1 is N-1, o(N1, X1, Y).
## Infinity Using the flags `float_overflow` and `float_zero_div` some arithmetic operations produce +/- infinity rather than an exception. Like ignoring underflows ignoring overflows may be dangerous, but can also result in valid approximations without the need to handle exceptions and perform the necessary reasoning about infinity outside Prolog arithmetic support. The syntax for infinite numbers is `1.0Inf` or `-1.0Inf`, both of which is otherwise invalid Prolog syntax.
A is 25.0**10 000.
A is -25.0/10.0**(-1000), Z is 25.0/10.0**(-1000).
A is -25.0/10.0**(-1000), B is 1/A.
## Float rounding ISO does not define how a function rounds the _true_ value to a representable floating point number. Most implementation will inherid the C99 default behavior which rounds to the _nearest_ representable float. This is typically fine, but does not allow for generating an interval that surely contains the _real_ (ℝ) value. SWI-Prolog allows for defining the float mode using the flag `float_rounding`
set_prolog_flag(float_rounding, to_negative), Low is sqrt(2), set_prolog_flag(float_rounding, to_positive), High is sqrt(2).
In addition, the function nexttoward/2 can be used to enumerate representatble floats and (for example) realise a safe interval for the constant __π__.
Low is nexttoward(pi, -inf), High is nexttoward(pi, inf).
## Undefined arithmetic Typically less useful is to avoid exceptions on undefined operations, such as `sqrt(-2)` in the absence of [complex numbers](https://en.wikipedia.org/wiki/Complex_number), but this too has its applications. Undefined floating point arithmetic is expressed by NaN (_Not a Number_), which uses the Prolog syntax `1.5NaN` and can be detected using float_class/2 with the class `nan`. The attractive aspect of NaN is that it propagates through the computation: any computation in which NaN is involved produces a NaN result. As a consequence, if a set of numbers is computed we know exactly which elements of this set have somewhere along the computation encountered an invalid operation. The behavior is controlled using the flag `float_undefined`
A is sqrt(-1), float_class(A, Class).
NaN is a strange value in Prolog. _Arithmetic_ comparison (=:=/2, </2, >/2, etc.) all fails, but NaN is a normal Prolog term and has a normal place in the _standard order of terms_ used by sort/2, @>/2, compare/3, etc. NaN is defined to be __before any number in the standard order of terms__.
A is log(0), float_class(A, Class), \+ A < 0, \+ A > 0, \+ A =:= 0, A @< 0, A @< 0.0.
#### Flags affecting floating point processing Note that these flags are, conform all SWI-Prolog flags, _thread specific_ and inherit their initial value from the creating thread.
:- set_prolog_flag(float_overflow, infinity).
:- set_prolog_flag(float_undefined, nan).
:- set_prolog_flag(float_underflow, error).
:- set_prolog_flag(float_zero_div, infinity).
:- set_prolog_flag(float_rounding, to_positive).