任意精度整数平方根算法?


9

是否有已知的次二次算法来计算n位整数的平方根的下限?

天真的算法是这样的

def sqrt(x):
    r = 0
    i = x.bit_length() // 2
    while i >= 0:
        inc = (r << (i+1)) + (1 << (i*2))
        if inc <= x:
            x -= inc
            r += 1 << i
        i -= 1
    return r

这需要O(n)迭代,每个迭代都涉及O(n)时间的增加,因此O(n^2)总的来说是时间。有什么更快的方法吗?我知道对于乘法来说,有一些特殊的算法比二次时间要好,但是对于平方根我找不到任何东西。


我对相关问题的回答可能会帮助cs.stackexchange.com/a/37338/12052。唯一的问题是,您需要凭经验找到必要方程的一部分,以调整其准确性。
Francesco Gramano 2015年

@FrancescoGramano:对不起,我认为没有帮助。
Aryabhata 2015年

顺便说一句,这个次二次需求是更大问题的一部分吗?因为在实践中,简单二次方和复杂次二次方之间的差异可能不会太大。还是仅仅是理论上的兴趣?
Aryabhata 2015年

@Aryabhata对不起,我之前没有看到您的评论。不,这不是更大的问题的一部分,只是好奇。

Answers:


5

您可以使用牛顿方法或许多其他方法中的任何一种来找到多项式根的近似值。p(x)=x2c

牛顿方法的收敛速度将是二次的,这意味着正确的位数在每次迭代中加倍。这意味着牛顿方法的次迭代就足够了。O(lgn)

牛顿方法的每次迭代都会计算

xj+1=xj(xj2c)/(2xj)=0.5xj+c2xj.

乘法的位复杂度为Ob lg b ,以将两个b位整数相乘(忽略lg lg b因子)。除法的位复杂度(精确到b位)是相同的。因此,可以以On lg n )个运算来计算每个迭代。乘以O lg n 迭代,我们发现计算n位精度的平方根的总运行时间为On lg nO (blgb)blglgbbO (nlgn)O(lgn)n。这是次二次的。O (n(lgn)2)

我认为更仔细的分析表明,可以将其改进为On lg n )的运行时间(考虑到我们只需要知道每个x j的精度在j位左右,而不是n位精度内) 。但是,即使是更基本的分析也已经显示出运行时间显然是次二次的。O (nlgn)xjjn


在二进制一还具有使用身份的大的初始猜测。代替计算的日志,可以近似登录2 X为一个数字的数量X。例如,登录2 101011 6x1/2=21/2log2xlog2xxlog21010116
Nick Alger 2015年

@DW:但是我们不是要寻找整数平方根吗?如果您仅使用整数算术进行牛顿方法迭代,那么我们需要针对声明进行其他辩护,不是吗?否则,我们已经假设精度足够高...对不起,如果我缺少明显的内容。O(logn)
Aryabhata

@DW: 如果c,则 “牛顿法的收敛速度”将不会是二次方。,并且我不知道非负实数的 c值会发生什么。c=0c您对乘法的位复杂度的估计比您的以下建议更严格另外,我们“需要知道每个大约在2以内”xj “精确度”。2j

@Aryabhata: 我们不是很“寻找整数平方根”。我们正在寻找“平方根的地板”。 您对整数算术问题是正确的,尽管浮点运算具有相同的位复杂度。

1
@RickyDemer,是的,是一个特例,因为p x 的根具有多重性2,但是当c > 0时,根具有多重性1,因此Newton方法的确具有二次收敛性。我假设没有人会使用牛顿法来计算c = 0的平方根(因为零的平方根显然是零)。那你想说什么 您的评论是微不足道的评论,可以通过在我的答案中添加“特殊情况下零的平方根”来解决,还是在这里我想念的更深?c=0p(x)c>0c=0
DW

7

牛顿方法的问题之一是它在每次迭代中都需要除法运算,这是最慢的基本整数运算。

但是,牛顿的平方根倒数方法却没有。如果是您要查找的数字1x,迭代:1x

ri+1=12ri(3xri2)

通常表示为:

d i = 1 w i x r i + 1 = r i + r i d i

wi=ri2
di=1wix
ri+1=ri+ridi2

那是三个乘法运算。除以二可以实现为右移。

现在的问题是不是整数。但是,您可以通过手动实现浮点,并在适当的时候进行大量的移位操作来进行补偿,从而进行操作。r

首先,让我们重新缩放x

x=22ex

x1xxr=1xx=2erx

r

ri=2eiri

riei

我们知道,牛顿的方法使精确有效数字的数量大约增加了一倍。因此我们可以选择:

ei+1=2ei

经过一点操作,我们发现:

ei+1=2ei
wi=ri2
xi=x22eei+1
di=2ei+1wixi2ei+1
ri+1=2eiriridi2ei+1

在每次迭代中:

xrix2e+ei

x=263231212231e=31r0=3e0=23412

然后:

e1=4,r1=11
e2=8,r2=180
e3=16,r3=46338
e4=32,r4=3037000481

eieei>2e

2633037000481×263231+32=3037000481

3037000499ei

bO(blogb)ri<2eiwieiei+1ei+12ei+1位数字。

O(eilogei)O(loge)O(2elog2e)O(elog2e)x

但是,此分析隐藏了一个重要原则,每个使用大整数的人都应记住:因为乘法的位数是超线性的,所以任何乘法运算都只能在具有当前精度大小的整数上执行(并且,我可能会补充,您应该尝试将数量级相似的数字相乘)。使用大于该整数的整数会浪费精力。常数因子很重要,对于大整数,它们非常重要。

ab2cabc


这是很棒的东西。不过,有一条评论:渐近除法的位复杂度与乘法的位复杂度近似相同吗?所以,您所谈论的是可以使常数因子改善而不是渐近改善的东西,对吗?从您的答案中并不能完全清楚。
DW

bO(blgb)O(blgb(lglgb)O(1))

1
@DW: bO(blogb)“位”一词只出现一次;否则我会指出这一点。

是的,这是恒定因素的问题。最佳的大整数除法算法使用的技术与整个算法非常相似,例如Newton-Raphson迭代并将每次迭代的有效精度加倍。Newton-Raphson循环中的Newton-Raphson循环基于常数因子!Ricky Demer是正确的;我在考虑RAM模型这个词。我可能应该提到这一点。
化名
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.