1. 牛顿法
先猜一个初值,然后依次迭代,直到结果足够精确。比如求number的平方根:
- X0 = guess
- X1 = (X0 + number / X0) / 2
- X2 = (X1 + number / X1) / 2
- ……
- Xn = (Xn-1 + number / Xn-1) / 2
结束条件可以是 abs(Xn * Xn – number) 小于某个数,或者两次迭代结果 abs(Xn – Xn-1) 小于某个数.
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
注意:上面这个代码不能使用第一个条件判断。因为此时求sqrt_newton(3)时,abs(val * val – x)最后一直是4.44089e-16,而numeric_limits
2. 二分法
二分法就是每次取中间的值,然后比较。直到结果足够精确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
3. 不知所云法
QUAKE-III里用来计算1/sqrt(x)的算法,速度快。 这里的float不能改成double,改成double就不对了。
还有个问题是,下面这个算法求出的结果精度会有点问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
补充知识:C++中的numeric_limits
numeric_limits定义于limits头文件中,主要用于取代C语言中limits.h中的那些宏。具体见它的参考页面
比如,
INT_MAX和INT_MIN使用numeric_limits<int>::max()和numeric_limits<int>::min()代替。
DBL_EPSILON使用numeric_limits<double>::epsilon()代替
References:
[1] 一个Sqrt函数引发的血案
[2] 维基百科-牛顿法