**Keywords**: floats.

joachim@ecrc.de Joachim Schimpf 6th December 1993Here are a some points about Prolog and floating point numbers that different Prologs handle differently and which should probably be addressed in the forthcoming ISO standard:

Should e.g.

X is 1/0.

raise an error or return infinity? (ECLiPSe does the former, SICStus the latter)

In the latter case, what is the syntax for the infinity value? I.e what should

X is 1/0, writeq(X).

print? Keep in mind that writeq/1 is supposed to print every Prolog term such that it can be read back using read/1. (SICStus prints inf, which is read back as an atom and thus wrong)

Is the infinity value a number or not, i.e. does

X is 1/0, number(X).

succeed or fail?

Same questions for IEEE NaNs, e.g. the result of X is sqrt(-2).

In IEEE arithmetic there are positive and negative zeros. Is Prolog allowed to show this difference to the user? For example, the following fails with SICStus and also with old versions of ECLiPSe:

0.0 is 0.0 * -1.0.

(the multiplication yields -0.0 which doesn't unify with 0.0)

Any opinions?

mcovingt@aisun3.ai.uga.edu Michael Covington 6th December 1993As I understand it, the draft Prolog standard picks up a different ISO standard for computer arithmetic, specifying lots of such things in detail. The standardizers felt that computer arithmetic should not be language-specific.

joachim@ecrc.de Joachim Schimpf 7th December 1993I realize that. But my posting was exactly about some problems that are

ted@crl.nmsu.edu Ted Dunning 7th December 1993Joachim Schimpf writes:

*(the multiplication yields -0.0 which doesn't unify with 0.0) *

In Prolog, unification is essentially useless for floats other than to assign values to previously unbound variables. The classic cause is the fact that you can have A = B, B = C, and A != C if you allow anything but strict bit equality. If you enforce strict bit equality for unification, then other things break.

jtai@yallara.cs.rmit.OZ.AU Chen Hiung Tai 9th December 1993Joachim Schimpf writes:

*Should e.g. *

*
*

X is 1/0.

*
raise an error or return infinity? *

Interesting point. In CLP system like CLP(R), this is handled by

A = B/C % assume { A,B,C } = number

rewriten to:

A * C = B

therefore

C = 0 then B = 0 & A = don't care

so

C = 0 & B != 0 then FAIL

I'm quite sure this is done in CLP(R) so at least there is one good reason (compatability) to do it this way. Unfortunately, complications arise when the equality is not ground. So, this method is not perfect.

ok@goanna.cs.rmit.oz.au Richard A. O'Keefe 9th December 1993Joachim Schimpf writes:

*Should e.g. *

*
*

X is 1/0.

*
raise an error or return infinity? *

The IEEE 754 standard is perfectly clear on this point. It *requires* as the default behaviour that 1.0/0.0 return +Infinity. It *recommends* in a non-normative appendix that there be some means by which a programmer can get an Overflow exception instead, If that person *explicitly* asks for it. Any system in which 1.0/0.0 *by default* raises an exception thereby fails to conform to IEEE 754.

When I was at Quintus, we found UNIX systems whose vendors claimed that
they conformed to 754 but failed to provide any means at all for
producing infinities. We also found UNIX systems which *did* conform to
754 but where the "please give me an exception" functions did not exist
or had no effect. Of course there are systems which don't claim to
follow 754 at all (IBM mainframes, Crays, ...) and there it may be
burdensome to emulate infinities.

The standard should not require conformance to IEEE 754.

The standard should not *forbid* conformance to IEEE 754 either.

Note that there are other things too. What about underflow? Should that return 0, or produce an exception? If you like exceptions, how about the IEEE 754 "Inexact" exception?

I suggest that the standard should define the exceptions that *may* be
raised, and simply state that the actual behaviour is implementation
defined, either an implementation will raise the exception or it will
yield some result instead and it must document which result. It can
also require an environment enquiry (I wrote a detailed paper on
floating point arithmetic for Prolog, it's available from the
University of Auckland) such as:

environment(floating_point_arithmetic(ieee(754)))

so that a program can tell in advance what it's likely to get.

Joachim Schimpf continues:

*In the latter case, what is the syntax for the infinity value?
I.e what should *

*
*

X is 1/0, writeq(X).

*
print? Keep in mind that writeq is supposed to print every Prolog term
such that it can be read back using read/1. *

One wants a form which would not have been syntactically legal as anything else. Something like

+1.0Infinity +{bits}QNaN -1.0Infinity -{bits}SNaN

would do fine. That is, something which looks like a floating point literal, but instead of a scaling factor beginning with "e" there is a block of several letters saying what kind of special value it is. (Note that there are lots of Quiet Not-a-Numbers and lots of Signalling ones, so the form for QNaNs and SNaNs needs the numeric part to say which one you got.)

Joachim Schimpf:

*Is the infinity value a number or not, i.e. does *

*
*

X is 1/0, number(X).

*
succeed or fail? *

It is a member of the algebra whose axioms are given by IEEE 754. It is a member in perfectly good standing. One of the reasons for having the thing in the first place is to make the floating-point algebra CLOSED. Treating infinities or NaNs as anything but numbers would miss the whole point.

Joachim Schimpf:

*Same questions for IEEE NaNs, e.g. the result of X is sqrt(-2). *

See above.

Joachim Schimpf:

*In IEEE arithmetic there are positive and negative zeros. Is Prolog
allowed to show this difference to the user? E.g. the following fails
with SICStus and also with old versions of ECLiPSe: *

*
*

0.0 is 0.0 * -1.0.

*
(the multiplication yields -0.0 which
doesn't unify with 0.0) *

If you DON'T make this difference visible to the user, it isn't IEEE 754 arithmetic. The distinction between zeros is not an optional feature. Note that

(+1.0)/(+0.0) => +1.0Infinity (+1.0)/(-0.0) => -1.0Infinity

This can be justified if you regard "0" as really standing for "epsilon" and Infinity as really standing for 1/epsilon.

It is quite clear from the IEEE standard that if

X is +0.0, Y is -0.0

then

X \== Y, \+ (X = Y)

but it is equally clear that

X =:= Y, \+ (X =\= Y).

If you do anything different, it isn't 754-conformant.