我想编写一个程序,让用户可以使用直尺和指南针绘制点,线和圆。然后我希望能够回答这个问题,“这三个点是否共线?”要正确回答,我需要在计算点时避免舍入误差。
这可能吗?我怎样才能代表记忆中的点?
(我查看了一些不寻常的数字库,但我没有发现任何声称提供确切算术和确保终止的精确比较的内容。)
答案 0 :(得分:8)
我认为唯一可行的方法是使用符号表示, 而不是试图直接表示坐标值 - 所以你会有 避免尝试将sqrt(2)之类的值强制转换为某种数字格式。你会 处理二进制无法有限表示的无理数 十进制或任何其他位置符号。
答案 1 :(得分:8)
是
我强烈推荐Introduction to constructions,这是一个很好的基本指南。
基本上你需要能够用constructible numbers来计算 - 数字是合理的,或者是a + b sqrt(c)的形式,其中a,b,c是先前创建的(参见第6页) PDF)。这可以用代数数据类型(例如Haskell中的data C = Rational Integer Integer | Root C C C
来完成,其中Root a b c = a + b sqrt(c))。但是,我不知道如何使用该表示来执行测试。
两种可能的方法是:
可构造数字是algebraic numbers的子集,因此您可以使用代数数字。 所有代数数都可以用它们是根的多项式来表示。这些操作是可计算的,所以如果用多项式q表示数字a,用多项式q表示b(p(a)= q(b)= 0),那么就可以找到一个多项式r,使得r(a + b) )= 0.这在Mathematica,example等一些CAS中完成。另见:Computional algebraic number theory - chapter 4
使用Tarski的测试并代表数字。它很慢(双指数左右),但有效:)例如:代表sqrt(2),使用公式x ^ 2 - 2&& x>你可以在那里写出线的方程,检查点是否是共线等。见A suite of logic programs, including Tarski's test
如果转向computable numbers,那么平等,共线等会变得不可判断。
答案 2 :(得分:5)
要稍微扩展 Jim Lewis 的答案,如果你想对可以通过精确算术的整数构造的点进行操作,你需要能够对表格的表示进行操作:
a + b sqrt(c)
其中a,b和c是有理数或上面给出的表示形式。 Wikipedia关于哪些要点是可构造的,有一篇相当不错的文章。
用这种表述来回答确切平等的问题(必要时建立共线性)是一个相当棘手的问题。
答案 3 :(得分:5)
如果您尝试比较各点的坐标,那么您就遇到了问题。暂且不考虑共线性,如何确定两点是否相同?
假设一个人已经给出了坐标,另一个是从某些其他坐标开始的罗盘直尺构造,你想确定它们是否是相同的点。无论哪种方式都是欧氏几何的定理,它不是你可以测量的东西。您可以通过发现它们的坐标中的某些差异来证明它们不相同(例如,通过计算每个的小数位,直到遇到差异)。但总的来说,证明它们是相同的,不能通过近似方法来完成。计算一些1/sqrt(2)
和sqrt(2)/2
扩展的小数位数,你可以证明它们非常接近,但你不会证明它们是平等的。这需要代数(或几何)。
同样,为了证明三个点是共线的,你需要定理证明软件。用它们的结构表示点A,B,C,并试图证明定理“A,B和C是共线的”。这很难 - 你的程序将证明一些定理而不是其他定理。更容易的是要求用户提供他们是共线的证明,然后验证(或反驳)该证明,但这可能不是你想要的。
答案 4 :(得分:2)
通常,可构造点可能具有任意复杂的符号形式,因此您必须使用符号表示来完全处理它们。正如Stephen Canon上面提到的,你经常需要a + b * sqrt(c)形式的数字,其中a和b是有理数,c是整数。此表单的所有数字在算术运算下形成一个闭集。我写了some C++ classes(参见rational_radical1.h)来处理这些数字,如果这就是你需要的那些。
也可以构造数字,这些数字是任意数量的有理数的自由基项的总和。当处理多个radicand时,数字在乘法和除法下不再关闭,因此您需要将它们存储为可变长度有理系数数组。然后,操作的时间复杂度将是术语数量的二次方。
更进一步,你可以构造任何给定数字的平方根,这样你就可能有嵌套的平方根。这里,表示必须是树状结构才能处理根层次结构。虽然难以实施,但原则上没有任何东西阻止您使用这些表示。我不确定可以构造哪些附加数字,但是超出某一点,你的符号表示将足以表达处理非常大的数字类别。
<强>附录强>
答案 5 :(得分:0)
如果网格轴是整数值,那么答案是相当直接的,这些点要么完全是共线,要么不是。
然而,通常情况下,一个使用实数(井,浮点),然后在屏幕上绘制整数空间中存在的舍入值。在这种情况下,您别无选择,只能选择容差并使用它来确定共线性。保持小,用户永远不会知道差异。
答案 6 :(得分:0)
我建议不要试着让它完全准确。
这样做的第一个原因就是你在这里问的问题,舍入错误以及浮点计算带来的所有东西。
第二个是你需要对输入进行舍入,因为鼠标和屏幕使用整数。因此,最初所有用户输入都是整数,输出将是整数。
此外,从可用性的角度来看,它更容易在另一个点的邻域中点击(例如在一行中),并且界面认为您正在点击该点本身。
答案 7 :(得分:0)
实际上,您似乎在问“计算机使用的正常数学(整数或浮点数)是否可以完美地表示实数,没有舍入错误?”当然,答案就是“不”。如果你想要理论上的正确性,那么你将会遇到更难的象征性操作问题,并编写相当于几何中完成的推论。 (简而言之,我同意上面的Steve Jessop。)
答案 8 :(得分:0)
希望他们可以提供帮助的一些想法。
你所谈论的那种结构需要乘法和除法,这意味着为了保持精确性,你必须使用有理数,这通常很容易在一个合适的大整数之上实现(即,无限大的)。 (Common Lisp有这些内置的,必须有其他语言。)
现在,您需要表示任意数字的平方根,并且必须将它们混合在一起。
因此,数字是以下之一:有理数,有理数乘以有理数的平方根(或者,也就是理性的平方根),或数字之和。为了证明什么,你将不得不将这些数字变成某种规范的形式,对于我可以随意计算的所有形式,这可能是烦人的并且计算成本很高。
这当然意味着用户将被限制在理性点,不能使用任意轮换,但这可能并不重要。