巴比伦广场根方法背后的数学

时间:2013-09-26 11:17:30

标签: algorithm math

我读了计算任意数字的平方根的方法,算法如下:

double findSquareRoot(int n) {
    double x = n;
    double y = 1;
    double e = 0.00001;
    while(x-y >= e) {
        x = (x+y)/2;
        y = n/x;
    }
    return x;
}

关于此方法的问题是

  1. 如何计算平方根?我不明白这背后的数学。 x=(x+y)/2 and y=n/x如何收敛于n的平方根。解释这个数学。

  2. 此算法的复杂性是什么?

4 个答案:

答案 0 :(得分:3)

很容易看出你是否进行了一些运行并打印了x和y的连续值。例如100:

50.5 1.9801980198019802
26.24009900990099 3.8109612300726345
15.025530119986813 6.655339226067038
10.840434673026925 9.224722348894286
10.032578510960604 9.96752728032478
10.000052895642693 9.999947104637101
10.000000000139897 9.999999999860103

请注意,诀窍是如果x 不是 n的平方根,那么它高于或低于真实根,n/x永远在另一边。因此,如果计算xn/x的中点,它将更接近真实的根。

关于复杂性,它实际上是无限的,因为真正的根将永远不会到达。这就是你拥有e参数的原因。

答案 1 :(得分:3)

这是Newton's method用于计算n的平方根的典型应用。您正在计算序列的限制:

x_0 = n
x_{i+1} = (x_i + n / x_i) / 2

您的变量x是当前字词x_i,而变量yn / x_i

要了解为什么必须计算此限制,您需要考虑函数:

f(x) = x^2 - n

您想要找到此功能的根目录。它的衍生物是

f'(x) = 2 * x

和牛顿的方法为您提供了公式:

x_{i+1} = x_i - f(x_i) / f'(x_1) = ... = (x_i + n / x_i) / 2

为了完整起见,我在这里复制@ rodrigo答案的基本原理,并结合我对它的评论。如果您想忘记Newton的方法并尝试单独理解此算法,这将非常有用。

  

诀窍是如果x不是n的平方根,那么它就是。y = n/x   近似值位于真实根之上或之下,而(x+y)/2始终位于真实根之上   另一边。因此,如果您计算x的中点,它将是。{   比这两个近似中最差的更接近真根   (yx)。当yd足够接近时,您就完成了。

这也可以帮助您找到算法的复杂性。假设r是两个近似值中最差的与真实根(x+y)/2的距离。然后,中点rd/2之间的距离最多为log(|n-sqrt(n)|/epsilon) (如果您绘制一条直线来显示它,它会对您有所帮助)。这意味着,每次迭代,距离减半。因此,最坏情况的复杂性是对数w.r.t。到初始近似的距离和所寻求的精度。对于给定的程序,它是

{{1}}

答案 2 :(得分:1)

我认为所有信息都可以是found in wikipedia

基本思想是,如果x高估了非负实数S的平方根,那么S / x将被低估,因此可以合理地预期这两个数字的平均值可以提供更好的近似。

每次迭代时,此算法会在答案中将正确的数字加倍,因此复杂性与所需精度的对数呈线性关系。

为什么会这样?如上所述here,如果你将进行无限次迭代,你会得到一些值,让我们把它命名为L.L必须满足等式L =(L + N / L)/ 2(如在算法中),所以L = sqrt(N)。如果你担心收敛,你可以计算每次迭代的平方相对误差(Ek是错误,Ak是计算值):

Ek =(Ak / sqrt(N) - 1)²
如果:
Ak =(Ak-1 + N / Ak-1)/ 2和Ak = sqrt(N)(sqrt(Ek)+ 1)
你可以得出Ek的递归关系:
Ek = Ek-1²/ [4(sqrt(Ek-1)+ 1)²]
并且它的限制是0,因此A1,A2 ...序列的限制是sqrt(N)。

答案 3 :(得分:1)

数学解释是,在小范围内,算术平均值是几何平均值的合理近似值,用于计算平方根。随着迭代越接近真正的平方根,算术平均值和几何平均值之间的差异消失,近似值变得非常接近。这是我最喜欢的Heron算法版本,它首先将输入 n 归一化,范围为1≤ n < 4,然后展开循环一定数量的迭代,保证收敛。

def root(n):
    if n < 1: return root(n*4) / 2
    if 4 <= n: return root(n/4) * 2
    x = (n+1) / 2
    x = (x + n/x) / 2
    x = (x + n/x) / 2
    x = (x + n/x) / 2
    x = (x + n/x) / 2
    x = (x + n/x) / 2
    return x

我讨论了几个计算my blog的平方根的程序。