我有以下代码:
:-use_module(library(clpfd)).
afn(A,B,C):-
C #= B*A.
它可以使用整数,但不能使用十进制数字:
43 ?- afn(20, 10, C).
C = 200.
44 ?- afn(20, -10, C).
C = -200.
45 ?- afn(20, -10.5, C).
ERROR: Domain error: `clpfd_expression' expected, found `-10.5'
46 ?-
我如何在这里使用小数?感谢。
编辑:我发现以下有小数的作品:
afn(A,B,C):-
C is B * A.
67 ?- afn(20.895, 40.5, C).
C = 846.2475.
'是'是一种正确的方法吗?!
答案 0 :(得分:3)
CLP(FD)通过整数实现推理。
要将声明性算术扩展为十进制数,基本上有两个选项:
我已经看到两种方法都成功应用了。选项(2)有时是优选的,因为CLP(FD)可以更广泛地使用,也因为你可以在有限域上成功地解决它的非线性约束。
编辑:在您的情况下,合适的查询可能如下所示:
?- afn(200, -105, C). C = -21000.
最后,您必须再次缩放结果。这样,您可以通过整数模拟小数。
请注意,使用浮动根本不是一个好的解决方案,因为您无法真正信任结果。因此,只要在Prolog系统中尚未广泛使用更高级的格式,就可以使用有理数或整数。
答案 1 :(得分:1)
你必须要区分
功能(或“模式”)算术。这是您熟悉的其他编程语言之一:您知道哪些参数是输入的,哪些是输出的,您只需计算输入的输出。这就是你从获得的结果2 (这是标准Prolog的一部分),如果这就是你想要的,那就坚持下去。
?- A=3, B=1.5, C is B * A.
C = 4.5
?- A=3, C=4.5, C is B * A.
instantiation fault <<< input B not kown
关系算术。在这里,您要说明必须在所涉及的变量之间保持的等式或不等式。没有输入/输出参数的概念。相反,系统的工作是确保在呈现变量解决方案时保持所有声明的关系。
实现关系算法有许多不同的方法,许多方法只适用于问题的子集(例如只有整数,或只有线性表达式),因此这些功能通常以库的形式提供。
对实数进行一般关系算术的一种可用实现是ECLiPSe的library(ic)(参见2,3),它将实数表示为浮点间隔:
?- A=3, C=4.5, C $= B * A.
B = 1.5__1.5 <<< precise result
?- C $= B * A, C=1, A=10.
B = 0.099999999999999992__0.1 <<< imprecise but accurate result
There are 2 delayed goals.
?- ln(X) $>= sin(X).
X = X{0.36787944117144228 .. 1.0Inf} <<< partially solved
There are 3 delayed goals.
话虽如此,使用区间运算并正确解释结果并不总是直截了当,这就是为什么@mat建议的解决方法可能有用(适用时)。