Arithmetic can be divided into some special purpose integer predicates and a series of general predicates for integer, floating point and rational arithmetic as appropriate. The general arithmetic predicates all handle expressions. An expression is either a simple number or a function. The arguments of a function are expressions. The functions are described in section 4.26.2.3.
The predicates in this section provide more logical operations between integers. They are not covered by the ISO standard, although they are `part of the community' and found as either library or built-in in many other Prolog systems.
inf
or
infinite
48We prefer infinite
,
but some other Prolog systems already use inf
for infinity
we accept both for the time being.
between/3
is true iff Value >=Low, a feature
that is particularly interesting for generating integers from a certain
value.not_less_than_zero
if called with a negative integer. E.g. succ(X, 0)
fails
silently and succ(X, -1)
raises a domain-error.49The
behaviour to deal with natural numbers only was defined by Richard
O'Keefe to support the common count-down-to-zero in a natural way. Up-to
5.1.8 succ/2
also accepted negative integers.The general arithmetic predicates are optionally compiled (see set_prolog_flag/2 and the -O command line option). Compiled arithmetic reduces global stack requirements and improves performance. Unfortunately compiled arithmetic cannot be traced, which is why it is optional.
Note that normally, is/2 should be used with unbound left operand. If equality is to be tested, =:=/2 should be used. For example:
?- 1 is sin(pi/2). | Fails!. sin(pi/2) evaluates to the float 1.0, which does not unify with the integer 1. |
?- 1 =:= sin(pi/2). | Succeeds as expected. |
SWI-Prolog defines the following numeric types:
bounded
, min_integer
and
max_integer
. As the use of GMP is default, most of the
following descriptions assume unbounded integer arithmetic.
Internally, SWI-Prolog has three integer representations. Small
integers (defined by the Prolog flag max_tagged_integer
)
are encoded directly. Larger integers are represented as 64-bit value on
the global stack. Integers that do not fit in 64-bit are represented as
serialised GNU MPZ structures on the global stack.
rdiv(N,M)
. Rational numbers that are
returned from is/2
are canonical, which means M is positive and N
and
M have no common divisors. Rational numbers are introduced in
the computation using the rational/1, rationalize/1
or the rdiv/2
(rational division) function. Using the same functor for rational
division and representing rational numbers allow for passing rational
numbers between computations as well as to format/3
for printing.
On the long term it is likely that rational numbers will become
atomic as well as subtype of number. User code that
creates or inspects the rdiv(M,N)
terms will not be
portable to future versions. Rationals are created using one of the
functions mentioned above and inspected using rational/3.
double
.
On most today platforms these are 64-bit IEEE floating point numbers.
Arithmetic functions that require integer arguments accept, in addition to integers, rational numbers with denominator `1' and floating point numbers that can be accurately converted to integers. If the required argument is a float the argument is converted to float. Note that conversion of integers to floating point numbers may raise an overflow exception. In all other cases, arguments are converted to the same type using the order below.
integer -> rational number -> floating point number
The use of rational numbers with unbounded integers allows for exact integer or fixed point arithmetic under the addition, subtraction, multiplication and division. To exploit rational arithmetic rdiv/2 should be used instead of `/' and floating point numbers must be converted to rational using rational/1. Omitting the rational/1 on floats will convert a rational operand to float and continue the arithmetic using floating point numbers. Here are some examples.
A is 2 rdiv 6 | A = 1 rdiv 3 |
A is 4 rdiv 3 + 1 | A = 7 rdiv 3 |
A is 4 rdiv 3 + 1.5 | A = 2.83333 |
A is 4 rdiv 3 + rational(1.5) | A = 17 rdiv 6 |
Note that floats cannot represent all decimal numbers exactly. The function rational/1 creates an exact equivalent of the float, while rationalize/1 creates a rational number that is within the float rounding error from the original float. Please check the documentation of these functions for details and examples.
Rational numbers can be printed as decimal numbers with arbitrary precision using the format/3 floating point conversion:
?- A is 4 rdiv 3 + rational(1.5), format('~50f~n', [A]). 2.83333333333333333333333333333333333333333333333333 A = 17 rdiv 6
Arithmetic functions are terms which are evaluated by the arithmetic predicates described in section 4.26.2. SWI-Prolog tries to hide the difference between integer arithmetic and floating point arithmetic from the Prolog user. Arithmetic is done as integer arithmetic as long as possible and converted to floating point arithmetic whenever one of the arguments or the combination of them requires it. If a function returns a floating point value which is whole it is automatically transformed into an integer. There are four types of arguments to functions:
Expr | Arbitrary expression, returning either a floating point value or an integer. |
IntExpr | Arbitrary expression that must evaluate into an integer. |
RatExpr | Arbitrary expression that must evaluate into a rational number. |
FloatExpr | Arbitrary expression that must evaluate into a floating point. |
For systems using bounded integer arithmetic (default is unbounded, see section 4.26.2.1 for details), integer operations that would cause overflow automatically convert to floating point arithmetic.
iso
is true
, both arguments are converted
to float and the return value is a float. Otherwise (default), if both
arguments are integers the operation returns an integer if the division
is exact. If at least one of the arguments is rational and the other
argument is integer, the operation returns a rational number. In all
other cases the return value is a float. See also ///2
and rdiv/2.%
operator. It's behaviour with
negative values is illustrated in the table below.
2 | = | 17 | mod | 5 |
2 | = | 17 | mod | -5 |
-2 | = | -17 | mod | 5 |
-2 | = | -17 | mod | -5 |
"a"
evaluates to the character code of the letter `a' (97). This option is
available for compatibility only. It will not work if `style_check(+string)
'
is active as "a"
will then be transformed into a string
object. The recommended way to specify the character code of the letter
`a' is 0'a
.rational(0.1)
. The function rationalize/1
remedies this. See section 4.26.2.2
for more information on rational number support.
?- A is rational(0.25). A is 1 rdiv 4 ?- A is rational(0.1). A = 3602879701896397 rdiv 36028797018963968
?- A is rationalize(0.25). A = 1 rdiv 4 ?- A is rationalize(0.1). A = 1 rdiv 10
floor(Expr)
. For Expr <
0 this is the same as
ceil(Expr)
. E.i. truncate rounds towards zero.Bitvector functions
The functions below are not covered by the standard. The msb/1 function is compatible to hProlog. The others are private extensions that improve handling of ---unbounded--- integers as bit-vectors.
(IntExpr >> N) /\ 1 =:= 1
.
This is the (zero-origin) index of the most significant 1 bit in the
value of IntExpr, which must evaluate to a positive integer.
Errors for 0, negative integers, and non-integers.(IntExpr >> N) /\ 1 =:= 1
.
This is the (zero-origin) index of the least significant 1 bit in the
value of IntExpr, which must evaluate to a positive integer. Errors for
0, negative integers, and non-integers.