Floating point 用swi-prolog实现奇异算法

Floating point 用swi-prolog实现奇异算法,floating-point,prolog,floating-accuracy,iso-prolog,Floating Point,Prolog,Floating Accuracy,Iso Prolog,我觉得结果很奇怪。为什么不是0.3?谁能告诉我为什么会有这样的结果?有可能解决这个问题吗 ?- X is 5.3-5. X = 0.2999999999999998. ?- 我的第二个问题是如何将“小时”符号“13.45”-->“15.30”转换为小时数?例如,上面计算的15.30-13.45期间将为1.85。但我需要在一个小时的部分时间里做手术,而不是在剩余的时间里做手术。像15 1/2-13/4,这种方式更好。我试着 ?- X is (5.3-5)*100/60. X

我觉得结果很奇怪。为什么不是0.3?谁能告诉我为什么会有这样的结果?有可能解决这个问题吗

 ?- X is 5.3-5.
    X = 0.2999999999999998.

    ?- 
我的第二个问题是如何将“小时”符号“13.45”-->“15.30”转换为小时数?例如,上面计算的15.30-13.45期间将为1.85。但我需要在一个小时的部分时间里做手术,而不是在剩余的时间里做手术。像15 1/2-13/4,这种方式更好。我试着

?- X is (5.3-5)*100/60.
X = 0.4999999999999997.

?- X is (5.3-5)*100//60.
ERROR: ///2: Type error: `integer' expected, found `29.999999999999982'

有什么建议吗?

这是由于浮点运算,它几乎总是不完美的。计算机以二进制工作,但人们大多以10为基数工作。这在这里和那里引入了一些不精确性;不精确的程度取决于硬件和软件的工作方式。但关键是你不能准确预测错误会是什么,只能预测会有错误

结果是你不能期望5.3-5正好是0.3;您需要测试它是否真的接近,比如在0.00000000000001之内。当得到第二个示例中的结果时,需要在使用结果之前显式转换为整数

[脚注:]根据下面的评论,我要补充的是,使用恰好是2的幂的浮点数的算术,也就是说,2^I或2的幂和,例如,7=4+2+1,可以由计算机精确计算。关于这是否真的是浮点运算,有一个哲学上的争论。但它解释了为什么,例如,大多数语言会报告2.0+1.0等于3,而0.2+0.1等于0.300000000004。

关于这一行:

X is (5.3-5)*100//60.
//谓词特别是整数除法,您正在对浮点进行操作。您可以这样做:

X is round((5.3-5)*100/60).

当然,在这两种情况下,都会得到0,因为如果进行浮点运算,它大约是0.3。所以不清楚这是否是你真正想要的

其他有趣的选择:

?- X is (5.3-5)*100/ 60.
X = 0.4999999999999997.

?- X is float(round((5.3-5)*100) rdiv 60).
X = 0.5.

您从SWI得到的答案是正确的。 在许多编程语言和几乎所有的Prolog系统中,浮点实现都基于二进制基数=2系统。在这个系统中,数字5.3无法精确表示,因此选择了一些近似值。减法特别适合于暴露这种不精确性

?- X is 5.3-5-0.3.
X = -1.6653345369377348e-16.
只要你用的是2的幂和,包括2-1,2-2。。。只要后面浮点数的精度允许,您将获得精确的结果:

?- X is 5.000244140625-5-0.000244140625.
X = 0.0.
符合ISO标准的Prolog系统所要做的是确保在使用写入选项quotedtrue写入浮点时,浮点的写入方式能够精确地读回

至于你的第二个问题:///2只定义在整数上。如果要将浮点转换为ISO Prolog中的整数,请使用常用的LIA-1函数:

地板/1,截形/1,圆形/1,天花板/1


但是,我建议使用div/2代替///2。出于充分的理由,///2的含义不再受LIA-1:2012标准ISO/IEC 10967-1:2012的支持。有关详细信息,请参阅和。

谢谢,我不知道“回合”的情况。非常简洁且有用。@vincent您可能想浏览SWI Prolog的算术函数:最近出现了一些非常类似的问题,问题是Pascal使用了大量的编译器魔法来掩盖浮点数的复杂性,当Prolog没有以同样的方式工作时造成混乱。这总是不完美的是不正确的。它适用于一定范围内基于基数2的数字。使用基于基数2的数字进行数学运算不是浮点运算。这些是不同的概念。虽然计算机在某些情况下甚至对于浮点运算也能产生正确的结果,但这并不意味着计算不精确;这意味着不精确性太小,无法进入分配给计算结果的内存空间。@EdCottell:有些数字是精确表示的,这些数字没有任何不精确性。如果你想知道细节,请咨询LIA-1。@false一些数字=/=浮点运算。你完全没有抓住我回答的重点。埃德,有一组数字接受浮点数表示,但精度丝毫没有损失。例如,Lua只有double,没有整数,因为将低于某个限制的整数表示为double并没有错误@false对“总是不完美”的普遍性提出了质疑。
?- X is 5.000244140625-5-0.000244140625.
X = 0.0.
?- X is round(5.3).
X = 5.