袖珍计算器算法
【袖珍计算器】是一种使用【指数函数 e x p exp exp】和【对数函数 l n ln ln】代替平方根的方法。
x \sqrt{x} x = x 1 2 x^{\frac{1}{2}} x21 = ( e l n x ) 1 2 (e^{lnx})^{\frac{1}{2}} (elnx)21 = e 1 2 ln x e^{\frac{1}{2} \ln x} e21lnx
注意: 由于计算机无法存储浮点数的精确值(浮点数的存储方法可以参考 IEEE 754,这里不再赘述),而指数函数和对数函数的参数和返回值均为浮点数,因此运算过程中会存在误差。例如当 x = 2147395600x=2147395600 时, e 1 2 ln x e 1 2 ln x e^{\frac{1}{2} \ln x}e^{\frac{1}{2}\ln x} e21lnxe21lnx的计算结果与正确值 46340 相差 1 0 − 11 10^{-11} 10−11 ,这样在对结果取整数部分时,会得到 46339 这个错误的结果。
因此在得到结果的整数部分 ans \textit{ans} ans 后,我们应当找出 ans \textit{ans} ans 与 ans + 1 \textit{ans} + 1 ans+1 中哪一个是真正的答案。
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
int ans = (int) Math.exp(0.5 * Math.log(x));
return (long) (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
}
}
牛顿迭代法
牛顿迭代法式一种可以快速求解函数零点的方法。
设函数:
y = f ( x ) = x 2 − C y = f(x) = x^2-C y=f(x)=x2−C
迭代 x i + 1 = 1 2 ( x i + C x i ) x_{i+1} = \frac{1}{2} (x_i + \frac{C}{x_i}) xi+1=21(xi+xiC)
细节
为什么选择 x 0 = C x_0 = C x0=C作为初始值?
- 因为 y = x 2 − C y = x^2 - C y=x2−C有两个零点 − C -\sqrt{C} −C和 C \sqrt{C} C 如果我们取的初始值较小,可能会迭代到 − C -\sqrt{C} −C这个零点,而我们希望找到的是 C \sqrt{C} C这个零点。因此选择 x 0 = C x_0 = C x0=C作为初始值,每次迭代均有 x i + 1 < x i x i + 1 x_{i+1} < x_ix i+1 xi+1<xixi+1,零点 C \sqrt{C} C 在其左侧,所以我们一定会迭代到这个零点。
迭代到何时才算结束?
- 每一次迭代后,我们都会距离零点更进一步,所以当相邻两次迭代得到的交点非常接近时,我们就可以断定,此时的结果已经足够我们得到答案了。一般来说,可以判断相邻两次迭代的结果的差值是否小于一个极小的非负数 ϵ ϵ ϵ,其中 ϵ ϵ ϵ 一般可以取 1 0 − 6 10^{-6} 10−6或 1 0 − 7 10^{-7} 10−7
如何通过迭代得到的近似零点得出最终的答案?
- 由于 y = f ( x ) 在 [ C , + ∞ ] y = f(x) 在 [\sqrt{C}, +\infty] y=f(x)在[C,+∞] 上是凸函数(convex function)且恒大于等于零,那么只要我们选取的初始值 x 0 x_0 x0大于等于 C \sqrt{C} C,每次迭代得到的结果 x i x_i xi都会恒大于等于 C \sqrt{C} C 。因此只要 \epsilonϵ 选择地足够小,最终的结果 x k x_k xk只会稍稍大于真正的零点 C \sqrt{C} C 。在题目给出的 32 位整数范围内,不会出现下面的情况:
真正的零点为 n − 1 / 2 ϵ n - 1/2ϵ n−1/2ϵ,其中 n 是一个正整数,而我们迭代得到的结果为 n + 1 / 2 ϵ n+1/2ϵ n+1/2ϵ。在对结果保留整数部分后得到 n,但正确的结果为 n - 1。
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
double C = x, x0 = x;
while (true) {
double xi = 0.5 * (x0 + C / x0);
if (Math.abs(x0 - xi) < 1e-7) {
break;
}
x0 = xi;
}
return (int) x0;
}
}
二分法
比较简单常用不做赘述。
温故知新 未央书斋