- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 ECLiPSe Prolog 的 lib(ic)
我从 David H. Bailey, "Resolving numerical anomalies in scientific computation." 偶然发现了以下问题Unum book 提到了我。事实上,这只是其中的一部分。首先,让我用 (is)/2
来表述这个方程。 。 此外,请注意,所有这些十进制数字都以基数 2 float (包含 IEEE)精确表示:
ECLiPSe Constraint Logic Programming System [kernel]
...
Version 6.2development #21 (x86_64_linux), Wed May 27 20:58 2015
[eclipse 1]: lib(ic).
...
Yes (0.36s cpu)
[eclipse 2]: X= -1, Y = 2, Null is 0.80143857*X+1.65707065*Y-2.51270273.
X = -1
Y = 2
Null = 0.0
Yes (0.00s cpu)
所以这真正 0.0(根本没有舍入)。但现在与 $=
相同代替is
:
[eclipse 3]: X= -1, Y = 2, Null $= 0.80143857*X+1.65707065*Y-2.51270273.
X = -1
Y = 2
Null = 2.2204460492503131e-16__2.2204460492503131e-16
Yes (0.00s cpu)
此区间不包含 0.0。我知道区间算术通常有点过于近似,如下所示:
[eclipse 4]: 1 $= sqrt(1).
Delayed goals:
0 $= -1.1102230246251565e-16__2.2204460492503131e-16
Yes (0.00s cpu)
但至少等式成立!然而,在第一种情况下,不再包括零。显然我还没有明白一些事情。我也尝试过eval/1
但没有效果。
[eclipse 5]: X= -1, Y = 2, Null $= eval(0.80143857*X+1.65707065*Y-2.51270273).
X = -1
Y = 2
Null = 2.2204460492503131e-16__2.2204460492503131e-16
Yes (0.00s cpu)
Null
的原因是什么?不包括0.0
?
(在 @jschimpf 令人惊讶的答案后编辑)
这是本书第 187 页的引文,我将其解释为数字被精确表示(现在划过)。
Use a {3,5}, environment, the one that can simulate IEEE single precision. The input values are exactly representable. ...
{-1, 2}
...
That did the job, computing the exact answer with fewer than half the bits used by ...
否则第 184 页的陈述成立:
...
0.80143857 x + 1.65707065 y = 2.51270273
这些方程看起来确实很简单。假设精确的十进制输入,该
系统可以通过x = -1和y = 2精确求解。这是通过 SICStus 重新检查的
library(clpq)
:| ?- {X= -1,Y=2,
A = 80143857/100000000,
B = 165707065/100000000,
C = 251270273/100000000,
Null = A*X+B*Y-C}.
X = -1,
Y = 2,
A = 80143857/100000000,
B = 33141413/20000000,
C = 251270273/100000000,
Null = 0 ?
yes所以 -1, 2 是精确解。
<小时/>精确的表述
这是一个在输入系数中不存在舍入问题的重新表述,但解仍然只是 -∞...+∞。因此基本正确,但不可用。
[eclipse 2]: A = 25510582, B = 52746197, U = 79981812,
C = 80143857, D = 165707065, V = 251270273,
A*X+B*Y$=U,C*X+D*Y$=V.
A = 25510582
B = 52746197
U = 79981812
C = 80143857
D = 165707065
V = 251270273
X = X{-1.0Inf .. 1.0Inf}
Y = Y{-1.0Inf .. 1.0Inf}
Delayed goals:
52746197 * Y{-1.0Inf .. 1.0Inf} + 25510582 * X{-1.0Inf .. 1.0Inf} $= 79981812
80143857 * X{-1.0Inf .. 1.0Inf} + 165707065 * Y{-1.0Inf .. 1.0Inf} $= 251270273
Yes (0.00s cpu)
最佳答案
这里有几个问题共同造成了困惑:
除了声明之外,示例中的三个常量不有双 float 的精确表示。
最初的示例不涉及舍入,这是不正确的。
第一个示例中看似正确的结果实际上是由于幸运的是舍入错误。其他计算顺序给出不同的结果。
准确的结果,给定最接近的双浮点表示常数确实不为零,而是 2.2204460492503131e-16。
区间运算只有在输入时才能给出准确的结果是准确的,但这里的情况并非如此。常数必须是扩大到包含所需小数的区间。
像 lib(ic) 提供的关系算术本质上就是这样做的不保证特定的评估顺序。由于这个原因,四舍五入错误可能与功能评估期间遇到的错误不同。然而,对于给定的常数,结果是准确的。
下面将进行更详细的介绍。正如我将演示一些使用 ECLiPSe 查询点,先简单介绍一下语法:
两个 float 用双下划线分隔,例如0.99__1.01
表示具有下限和上限的区间常数,在本例中1附近的数字。
两个整数之间用一个下划线分隔,例如 3_4
表示具有分子和分母的有理常数,在此情况四分之三。
为了演示第 (1) 点,请将浮点表示形式转换为0.80143857 变为有理数。这给出了精确的分数3609358445212343/4503599627370496,很接近,但不相同,到预期的小数 80143857/100000000。 float 因此,表示方式不准确:
?- F is rational(0.80143857), F =\= 80143857_100000000.
F = 3609358445212343_4503599627370496
Yes (0.00s cpu)
下面显示了结果如何取决于评估顺序(上面第 3 点;请注意,我已通过以下方式简化了原始示例去掉不相关的乘法):
?- Null is -0.80143857 + 3.3141413 - 2.51270273.
Null = 0.0
Yes (0.00s cpu)
?- Null is -2.51270273 + 3.3141413 - 0.80143857.
Null = 2.2204460492503131e-16
Yes (0.00s cpu)
顺序依赖性证明存在舍入误差(第 2 点)。对于熟悉浮点运算的人来说,实际上很容易看出添加 -0.80143857 + 3.3141413
时,0.80143857
的两位精度在调整操作数的指数时迷失方向。事实上它是这个幸运的舍入错误给了OP看似正确的结果!
实际上,第二个结果相对于常量的浮点表示。我们可以证明这一点通过使用精确的有理算术重复计算:
?- Null is rational(-0.80143857) + rational(3.3141413) - rational(2.51270273).
Null = 1_4503599627370496
Yes (0.00s cpu)
?- Null is rational(-2.51270273) + rational(3.3141413) - rational(0.80143857).
Null = 1_4503599627370496
Yes (0.00s cpu)
由于加法是通过精确的有理数完成的,所以现在的结果是与顺序无关,并且因为 1_4503599627370496 =:= 2.2204460492503131e-16
,这证实了上面获得的非零浮点结果(第 4 点)。
区间算术在这里有何帮助?它的工作原理是通过计算包围真值的间隔,这样结果总是输入准确。所以至关重要的是输入区间(ECLiPSe 术语中的有界实数)包含期望的真实值。这些可以通过编写它们来获得显式向下,例如0.80143856__0.80143858
;通过从精确的数字进行转换,例如使用有理数真实(80143857_100000000)
;或者通过指示解析器自动将所有 float 扩大到有界实数区间,如下所示:
?- set_flag(syntax_option, read_floats_as_breals).
Yes (0.00s cpu)
?- Null is -0.80143857 + 3.3141413 - 2.51270273.
Null = -8.8817841970012523e-16__1.3322676295501878e-15
Yes (0.00s cpu)
?- Null is -2.51270273 + 3.3141413 - 0.80143857.
Null = -7.7715611723760958e-16__1.2212453270876722e-15
Yes (0.00s cpu)
现在两个结果都包含零,并且很明显结果的精度取决于评估顺序。
关于prolog - lib(ic) 的精确解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31058929/
我正在学习序言。 在我看来,prolog 的规则(关系和简单的事实)是“肯定的”——他们说的是或可能是真的。 向 prolog 程序添加新的此类规则只会增加“正面”知识。它不能添加“负面”事实来说明某
希望你一切都好。我是 prolog 的新手,我在编写代码时遇到问题。这段代码的目的很简单。它将列表中的每个元素添加到最后一个。我可以用 Java 做的事情是: static void add(
在closed-world assumption下, what is not currently known to be true, is false Prolog 的语义通常被称为遵循封闭世界假设,
我正在 Prolog (swi-prolog) 中做我的第一步,但无法解决以下问题:如何将存在量化的规则包含在我的事实中;具体来说,我如何包含句子“每个人都是某人的 friend ”\forall x
我知道如何以过程方式(即,在 C++、Java 等中)对 BST 执行范围查询,但我发现很难转换为 Prolog 语言。 程序的方式应该是这样的: http://www.geeksforgeeks.o
Prolog 中是否有(相对)当前最佳实践的引用资料?一本适合没有学习过逻辑编程或“Prolog 的工艺”等高级文本的商业 Prolog 开发人员? 有很多通用教程,但我能找到的关于最佳实践的唯一一个
这是CFG: S -> T | V T -> UU U -> aUb | ab V -> aVb | aWb W -> bWa | ba 所以这将接受某种形式的: {a^n b^n a^m b^m |
我目前有以下问题,我想用 Prolog 解决。这是一个简单的例子,很容易在 Java/C/whatever 中解决。我的问题是,我认为与 Java 的思想联系太紧密,无法以利用 Prolog 逻辑能力
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我无法理解差异列表,尤其是在这个谓词中: palindrome(A, A). palindrome([_|A], A). palindrome([C|A], D) :- palindrome(A
(这不是一个类(class)作业问题。只是我自己的个人学习。) 我正在尝试在 Prolog 中进行练习以从列表中删除元素。这是我的代码: deleteall([],X,[]). deleteall([
我最近试图了解 Prolog,它似乎可以很好地映射到很多领域,但我无法弄清楚它可能不擅长什么。 那么它有什么不好的(除了需要实时/无 gc 性能的东西)? 最佳答案 我同意你的一般评估,即 Prolo
我正在组装一个简单的元解释器,它输出证明的步骤。我无法将证明步骤作为输出参数。我的谓词 explain1 以我想要的详细形式返回证明,但不是作为输出参数。我的谓词 explain2 将证明作为输出参数
hi(g,plus(A,B),int) :- hi(g,A,int),hi(g,B,int),!. 在上面的语句中 '!' 是什么意思?在声明的末尾签名吗? 最佳答案 那是 cut operator
有没有一种简单的方法可以让 prolog 中的查询只返回每个结果一次? 例如我正在尝试类似的东西: deadly(Xn) :- scary(X), Xn is X - 1, Xp is X + 1,
我正在尝试学习 Prolog。这是我使用这种语言的第一步。作为练习,我想编写可以识别一些扑克手牌的程序(同花顺、同花顺、满屋等)。 我正在 Prolog 中寻找良好的卡片表示。我需要有可能检查一张卡片
我刚刚被介绍到 Prolog 并且正在尝试编写一个谓词来查找整数列表的最大值。我需要写一个从头开始比较,另一个从结尾比较。到目前为止,我有: max2([],R). max2([X|Xs], R):-
我试图在Prolog中编写谓词palindrome/1,当且仅当其列表输入包含回文列表时才为true。 例如: ?- palindrome([1,2,3,4,5,4,3,2,1]). 是真的。 有什么
我正在尝试编写一个程序,该程序将两个列表作为输入并检查适当的子集。我开始于: proper([A],[]). proper([],[A]). proper([A|T1],[A|T2]) :- prop
我是 Prolog 的新手,我正在使用 SWI-Prolog v6.6 在 *.pl 中存储断言文件。 :- dynamic fact/2. assert(fact(fact1,fact2)). 使用
我是一名优秀的程序员,十分优秀!