问题
How to convert float to integer in prolog?
I tried:
?- integer(truncate(sqrt(9))).
false.
?- integer(round(sqrt(9))).
false.
回答1:
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 clpfd for more information.
回答2:
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.
来源:https://stackoverflow.com/questions/4354503/convert-float-to-integer-in-prolog