As discussed at length in a previous thread (Arithmetic functions rational/1 and rationalize/1), the arithmetic comparisons in most Prologs tested are mathematically incorrect, largely due, I suspect, to the ISO standard which says mixed numeric type comparisons are to be done by converting non-float values to floats before comparing with a float. Rounding errors can result in numbers appearing to be equal which are not, leading to logical inconsistencies (depending on your interpretation of floating point numbers), e.g.,
?- 1.1 =:= 11r10.
true.
?- 1.1*1.1 =:= 11r10*11r10.
false.
?- 2^1024 < inf.
false.
It was deemed unacceptable to change the current arithmetic comparison semantics since that could jeopardize compatibility with other Prologs and possibly(?) adversely affect the semantics of currently working code. However, it was suggested that adding arithmetic functions to support mathematically correct comparisons as an alternative would be acceptable. So a proposal:
Add a compare(N1,N2)
arithmetic function where N1
and N2
are numbers, or expressions which evaluate to numbers, and are interpreted as point values on the (ordered) real number line. This function returns -1
if N1
is less than N2
, 0
if N1
equals N2
and 1
if N1
is greater than N2
; all comparisons being mathematically correct, i.e., not subject to rounding errors. Simple examples:
% 2 < pi
?- N1 = 2, -1 =:= compare(N1,pi).
N1 = 2.
% 1.1 =\= 11r10
?- N1 = 1.1, N2 = 11r10, 0 =\= compare(N1,N2).
N1 = 1.1,
N2 = 11r10.
If either N1
or N2
is nan
, compare/2
either evaluates to nan
or and error is generated depending on the value of the float_undefined
global environment flag.
An additional use of this function is the reification of comparison operations, i.e., the conversion of the boolean result of a comparison to a number.
In addition, functions maxreal/2
and minreal/2
, similar to max/2
and min/2
, using mathematically correct compare would be supported. These two functions would also differ from the current max/2
and min/2
in that they would favour any rational (precise) value in the case of equality, so as to avoid unnecessary âpollutionâ of precise arithmetic with floats.
Note that any mixed mode arithmetic is unaffected by these functions, i.e. rounding errors will occur when floats are involved. But they do provide equivalent functionality to that found in other languages, e.g., CommonLisp and Python, without affecting existing Prolog compatibility, and without introducing any new global arithmetic flags (which are already complicated enough).