📚【笔记】牛顿迭代法
原理
我们尝试解出 \(f(x)\) 的一个近似解 \(x\) 。
从一个初始的近似解 \(x_0\) 开始。
与 \(f(x)\) 切于 \(\left(x,f(x)\right)\) 的直线 \(l\) 与 \(x\) 轴的交点 \(x_{i+1}\) 为一个更优解。
根据导数几何意义:
\[f'(x) = \frac{f(x_i)}{x_i-x_{i-1}}
\]
于是更优解 \(x_{i+1}\) 即可表示为:
\[x_{i+1} = x_i-\frac{f(x_i)}{f'(x_i)}
\]
牛顿迭代法的收敛率是平方级别的,这意味着每次迭代后近似解的精确数位会翻倍。
应用
求解平方根
我们想求 \(\sqrt n\) ,即 \(f(x) = x^2 - n\) 的一个近似解 \(x\) 。
又知 \(f'(x) = 2 \cdot x\) ,则:
\[x_{i+1} = \frac{x_i+\frac{n}{x_i}}{2}
\]
typedef unsigned long long ull;
double _eps = 1e-12;
ull s_n_tmp1, s_n_tmp2;
double sqrt_newton(double _n) {
s_n_tmp1 = ull(_n);
register double _x, _x_n;
if(s_n_tmp2 = (s_n_tmp1>>32))
_x = 1LL<<(32-(__builtin_clz(s_n_tmp2)>>1));
else
_x = 1LL<<(16-(__builtin_clz(s_n_tmp1)>>1));
while(1) {
_x_n = (_x+_n/_x)/2;
if(fabs(_x-_x_n) < _eps)
break;
_x = _x_n;
}
return _x;
}
比拟合数据制定初始值常数靠谱多了。
而且效率几乎与最优的拟合值一致。