convert float to integer in prolog
Asked Answered
C

2

7

How to convert float to integer in prolog?

I tried:

?- integer(truncate(sqrt(9))).
false.

?- integer(round(sqrt(9))).
false.
Crook answered 4/12, 2010 at 16:27 Comment(1)
Do you mean ?- X is round(sqrt(9)), integer(X) . You cannot call directly integer/1, the argument of integer/1 will not be evaluated.Afield
U
16

The predicate integer/1 that you used is true iff its argument is an integer. Since the term truncate(sqrt(9)) is not an integer, the predicate does not hold and therefore fails for this term.

There are at least two ways to get what you want:

Solution 1: Quick and broken

You can use the predicate (is)/2 for conversion between different number representations. In particular, check out the arithmetic functions round, truncate and ceiling. For example:

?- X is round(sqrt(9)).
X = 3.

However, note that using floating point numbers is always highly problematic. For example:

?- X is sqrt(2^10000).
ERROR: is/2: Arithmetic: evaluation error: `float_overflow'

There are also other issues such as rounding errors and possible underflow.

Solution 2: Quick and general

Due to the inherent shortcomings of floating point numbers, I strongly recommend you use more general mechanisms instead. For example several Prolog systems support rational numbers and integers with unbounded precision, whereas floats are always limited to machine precision.

If you need integer square roots, use for example finite domain constraints. With constraints, it suffices to state what holds for an integer X that denotes the positive square root:

?- X*X #= 9, X #>= 0.
X = 3.

This also works for larger integers:

?- X*X #= 2^10000, X #>= 0.
X = 1412467032...(1496 digits omitted)

See for more information.

Uthrop answered 4/12, 2010 at 16:49 Comment(1)
You should also talk about the benefits of float numbers. They don't need much space. If you want you could also use adaptive floats, which would kind of adapt their precision to the problem at hand. Not sure whether some CLP(R) can do that already.Afield
A
-1

Many Prolog systems provide an additional evaluable function integer/1, which returns an integer instead of a float compared to the evaluable function truncate/1 when the later is implemented like the FPU instruction.

The FPU semantics is available in a couple of Prolog systems like ECLiPSe Prolog and Jekejeke Prolog. The different behaviour is seen for large numbers:

/* with float semantics */
?- X is truncate(3.0E100).
X = 3.0E100

/* with integer semantics */
?- X is integer(3.0e100).
X = 299999999999999985344178410670684
7048562051886831693752693714362110399
5064698733443536124752361947136

This function integer/1 is not found in the ISO core standard. I was testing:

?- X is integer(3.1415).
X = 3

I could figure out the following support:

System          Available
GNU Prolog      No
Ciao Prolog     Yes
YAP Prolog      Yes
SICStus Prolog  Yes
ECLiPSe Prolog  Yes (1)
SWI-Prolog      Yes (2)
Jekejeke Prolog Yes

(1) ECLiPSe Prolog throws an error if argument is not
already integer. So needs to be combined with truncate/1 etc..
An alternative would be to use fix/1, although there
is a claim that fix/1 is deprecated.

(2) SWI-Prolog does not do a truncate, rather a round.
There is a claim that integer/1 itself is deprecated.

Afield answered 12/2, 2020 at 19:49 Comment(2)
In ISO Prolog, this functionality is provided by truncate/1. See truncateF→I of 9.1.6Kendricks
Concerning the current de-factor standard of big num GMP, if you prefer unncessarely filling memory bytes with zero, you might want to use the integer semantics for large floats.Afield

© 2022 - 2024 — McMap. All rights reserved.