我觉得结果很奇怪。为什么不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'
有什么建议吗?
答案 0 :(得分:3)
您从SWI获得的答案是正确的
在许多编程语言和几乎所有Prolog系统中,浮点实现基于二进制(radix = 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系统 要做的是确保在使用写选项quoted(true)
编写浮点数时,浮点数的写入方式可以回读精确。
关于你的第二个问题:(//)/2
仅在整数上定义。如果要将float转换为ISO Prolog中的整数,则通常使用LIA-1函数:
floor/1, truncate/1, round/1, ceiling/1
。
?- X is round(5.3).
X = 5.
但是,我建议您使用(div)/2
代替(//)/2
。 LIA-1:2012(标准ISO / IEC 10967-1:2012)不再支持(//)/2
的含义 - 有充分理由。有关详细信息,请参阅this和this answer。
答案 1 :(得分:2)
关于这一行:
X is (5.3-5)*100//60.
//
谓词是特定的整数除法,你在浮点运算。你可以这样做:
X is round((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.
答案 2 :(得分:1)
这是由于浮点运算(几乎 * )总是不完美的。计算机以二进制方式工作,但人们大多在10号基地工作。这在这里和那里引入了一些不精确的东西;不精确的程度取决于硬件和(有时)软件的工作原理。但关键是你无法准确预测错误是什么,只会出现错误。
结果是您不能指望5.3-5
正好0.3
;您需要测试它是否真正关闭(例如在0.00000000000001内)。当您获得第二个示例中的结果时,您需要在使用结果之前显式转换为整数。 You can read more in this answer
[脚注:]根据下面的评论,我将使用恰好是2的幂(即2 ^ i)或2的幂的总和(例如,7 = 4 + 2)的浮点数来添加该算术+1)可以由计算机精确计算。关于这是否实际上是“浮点算术”,存在一个哲学论证。但它解释了为什么,例如,大多数语言会报告2.0 + 1.0
为3
,但0.2 + 0.1
类似于0.30000000000000004
。