题目
给一个浮点数 x > 0 x>0 x>0,计算 x \sqrt x x,返回值也为float类型。
随想
之前一次面试,被问到这个题。当时忘了解法,用泰勒展开,折腾半天,啥也没搞出来,无奈写了二分法。这里写篇博客强记一下。
思路
牛顿法!牛顿法!牛顿法!
我直接把这个题泛化一下,假设是开
k
k
k次方,
k
∈
N
k \in \mathbb{N}
k∈N且
k
>
1
k > 1
k>1。为了防止搞混,记输入的
x
x
x为
x
0
x_0
x0,那么实际上就是求下式的零点:
y
=
x
k
−
x
0
(1)
y = x^k - x_0 \tag{1}
y=xk−x0(1)
注意构造的方式(面试的时候脑子木了好久),我们通过迭代的方式不断逼近真实结果,初始迭代直接采用 x 0 x_0 x0,记第 n n n次迭代后为 x n x_n xn,由图易得
x
n
+
1
=
x
n
−
y
n
y
n
′
(2)
x_{n+1} = x_{n} - \frac{y_{n}}{y_{n}'} \tag{2}
xn+1=xn−yn′yn(2)
注意上式即为牛顿法的一般公式,牛顿法和泰勒展开的一阶近似求零点是一样的,即求下式的零点
y
=
f
(
x
n
)
+
f
(
x
n
′
)
(
x
−
x
n
)
(3)
y = f(x_n) + f(x_n')(x - x_n) \tag{3}
y=f(xn)+f(xn′)(x−xn)(3)
回到本题,把式(1)代入(2),得到
x
n
+
1
=
(
1
−
1
k
)
x
n
+
x
0
k
1
x
n
k
−
1
=
1
k
[
(
k
−
1
)
x
n
+
x
0
x
n
k
−
1
]
(4)
x_{n+1}=(1 - \frac{1}{k})x_n + \frac{x_0}{k}\frac{1}{x_n^{k-1}}=\frac{1}{k}[(k-1)x_n + \frac{x_0}{x_{n}^{k-1}}] \tag{4}
xn+1=(1−k1)xn+kx0xnk−11=k1[(k−1)xn+xnk−1x0](4)
当
k
=
2
k=2
k=2时,上式为
x
n
+
1
=
1
2
x
n
+
x
0
2
1
x
n
=
1
2
(
x
n
+
x
0
x
n
)
(4)
x_{n+1}=\frac{1}{2}x_n + \frac{x_0}{2}\frac{1}{x_n}=\frac{1}{2}(x_n+\frac{x_0}{x_n}) \tag{4}
xn+1=21xn+2x0xn1=21(xn+xnx0)(4)
代码
float my_sqrt(float x, float epsilon) { // x > 0; 正确结果和返回值之间的误差上界为epsilon
float x0 = x;
while (((x - epsilon) * (x - epsilon) > x0 && x > epsilon)
|| (x + epsilon) * (x + epsilon) < x0) {
x = (x + x0 / x) / 2;
}
return x;
}