0
votes

I have to write a piece of prolog where I have to calculate which position in an array is used to store a value. However the result of these calculations should return an integer, so I use the floor/1 predicate to get myself the integer of the value but this doesn't work in my code. It keeps returning a number with decimal point, for example 3.0 instead of 3

The following is my code:

assign_value(El, NumberArray, RowNumber, I) :-
    ground(El),
    Number is NumberArray[El],
    Col is I/3,
    Row is RowNumber/3*3,
    Sum is floor(Col + Row + 1),
    subscript(Number, [Sum], El).
assign_value(_, _, _, _).

The result of the Sum is floor(Col + Row + 1) is never an integer and I don't know why. Can anyone help me with this?

3

3 Answers

2
votes

In ISO Prolog, the evaluable functor floor/1 has as signature (9.1.1 in ISO/IEC 13211-1):

floorF→I

So it expects a float and returns an integer.

However, I do not believe that first creating floats out of integers and then flooring them back to integers is what you want, instead, consider to use (div)/2 in place of (/)/2 thereby staying with integers all the time.

1
votes

Reading the documentation for floor/2, we see that

[floor/2] works on all numeric types. The result value is the largest integral value that is smaller that Number (rounding down towards minus infinity).

The result type is the same as the argument type. To convert the type to integer, use integer/2.

So you get the same type you supplied as the argument. Looking further at your predicate, we see the use of the / operator. Reading the documentation further, we see that

'/'/3 is used by the ECLiPSe compiler to expand evaluable arithmetic expressions. So the call to /(Number1, Number2, Result) is equivalent to

Result is Number1 / Number2

which should be preferred for portability.

The result type of the division depends on the value of the global flag prefer_rationals. When it is off, the result is a float, when it is on, the result is a rational.

Your division operation never returns an integer, meaning that things get upcast to floating point.

If you want to perform integer division, you should use the operators // or div.

1
votes

From the documentation of floor/2 (http://www.eclipseclp.org/doc/bips/kernel/arithmetic/floor-2.html)

The result type is the same as the argument type. To convert the type to integer, use integer/2.

For example:

...,
Floor is floor(Col+Row+1), Sum is integer(Floor).