Math 我如何比较表格a和x2B的数字;b*sqrt(c)没有中间整数变得越来越大?

Math 我如何比较表格a和x2B的数字;b*sqrt(c)没有中间整数变得越来越大?,math,language-agnostic,sqrt,Math,Language Agnostic,Sqrt,我正在开发一个应用程序,用于解决二维欧几里德几何中涉及圆和线()的二次约束,并以图形方式表示结果。我发现了在二叉树中表示此类问题的方法,但我遇到了一个实现问题: 我需要比较a+b*sqrt(c)形式的数字,以进行小于、大于和等于的标准关系运算。我的应用程序的c值限制为2、3、5、6、10、15或30。例如(类似C的伪代码,^是“操作员的权力”): 这种幼稚的实现需要我多次乘法,因此32位整数变成64位整数,然后变成128位整数,等等。我不想在实现中使用自定义BigInteger来存储仅用于比较的

我正在开发一个应用程序,用于解决二维欧几里德几何中涉及圆和线()的二次约束,并以图形方式表示结果。我发现了在二叉树中表示此类问题的方法,但我遇到了一个实现问题:

我需要比较
a+b*sqrt(c)
形式的数字,以进行小于、大于和等于的标准关系运算。我的应用程序的
c
值限制为
2
3
5
6
10
15
30
。例如(类似C的伪代码,
^
是“操作员的权力”):

这种幼稚的实现需要我多次乘法,因此32位整数变成64位整数,然后变成128位整数,等等。我不想在实现中使用自定义BigInteger来存储仅用于比较的临时值

我也不希望使用浮动,并希望避免在尝试直接将
sqrt(c)
作为浮动计算时出现舍入错误的风险。我需要这个应用程序的精确计算,不一定是无限精度的,但我希望避免舍入误差并确保结果正确


我如何在不需要巨大的中间整数值的情况下比较a+b*sqrt(c)形式的可构造数?我的
a
b
的初始值在32位范围内

****更新**** 谢谢大家的回复。根据继续求连分数的建议,我能够使用生成任意精确的平方根近似值

我还发现,它讨论了整数与定点表示的实数近似值相乘时的误差累积。幸运的是,我感兴趣的所有平方根的整数部分最多为6(只需要3位),因此我有很多位可以表示近似值的小数部分。对于32位整数的乘法,我需要位的最小定点近似值,以使乘法后的误差保持在1位


因此,虽然53位精度
double
足以存储足够精确的平方根近似值,但不足以存储与32位整数相乘后的结果,因为这需要最低67位精度以最小化错误。使用64位整数(比如Q16.48)的定点表示法来表示
c
和32位整数
b
,我计划使用96位或128位数字的多字算术来进行比较,而不会产生足够的错误来抛出结果。我相信这对于比较仅使用这7个平方根的可构造数字来说足够精确,但我对第二种观点感兴趣。有什么想法吗?

我不认为有一个公式可以让您在64位以内进行精确比较,假设您的值使用了完整的32位。我看到的问题是,a+b*sqrt(c)形式的数字在实数中是稠密的(假设c不是正方形),所以你会得到非常微妙的比较,需要很多精度。因此,您基本上需要通过平方来消除平方根,这将使用3次乘法

在这种情况下,BigInt实现实际上并没有那么糟糕,因为您只需要实现乘法、加法、减法和比较。这些可以在很少的代码行中有效地实现。通常情况下,最烦人的是部门的实施。此外,您知道您的数字永远不会溢出包含两个64位单元的数组,因此您实际上不需要跟踪产品中的位数


编辑:关于Thomas和Nemo对此的评论所建议的双精度的使用,通过使用连分数表示法,实际上很容易找到在sqrt(2)的2^{-53}范围内使用32位整数的近似值。

a
b
是有符号整数,是吗?是的。a和b是有符号整数。预计算平方根并使用双精度。它有53位尾数,所以不太可能有任何舍入错误。我的意思是,浮点数是专门为此而设计的,在这种情况下,花费大量时间来保持整数计算是不值得的。@Thomas:你确定两个32位数字的比率不可能在sqrt(2)、sqrt(3)、sqrt(5)等的2^(-53)之内吗。?你能证明吗?如果不是,使用双重密码会有给出错误答案的风险。。。如果B/A非常接近于SqRT(3),请考虑将-B*SqRT(3)与零进行比较。你能证明sqrt(3)的53位精度在这里从未给出错误的答案吗?同样地,对于每一个被问及的可能的比较?在这里使用
double
非常危险,我想。把问题提出来。你可能是对的(+1)。但是,考虑到
c
的有限值集,我想知道是否有一些技巧。例如,如果我们只对a+b*sqrt(2)和a,b非负表示感兴趣,我们可以使用“base sqrt(2)”表示来允许64位的快速比较。也许可以使用它的一些巧妙扩展来避开完整的BigInt实现。Re:续分数。这就是我的想法:-)@Nemo和Edvard,我考虑过连分数,我对它们的主要问题是,因为它们是一个递归过程(至少Gosper的实现是这样),我“我不确定在收到答复时会有什么样的时限,我知道这对我的申请很重要。如果我知道一个确定的时间上限(例如,不超过n次迭代),那么我会更乐意使用CF方法。@Nemo,基本sqrt(2)的问题是它不适用于sqrt(3)、sqrt(5)等(尽管非常有趣)。我认为实际的lim
boolean CompareConstructibleNumbers(int a1, b1, c1, a2, b2, c2)
{
    return a1plusb1sqrtc1_is_greater_than_a2plusb2sqrtc2 = 
        4 * ((a1 - a2)^2) * (b1^2) * c1
          > ((b2^2) * c2 - (b1^2) * c1 - (a1 - a2)^2)^2;
        // Not sure if I have the direction right for >
}