我写了一个程序,看起来与我在网上看到的其他递归牛顿平方根函数非常相似。由于某种原因,这个只适用于完美的方块,我似乎无法找到原因。我试过传递3个变量(epsilon),设置x = a,将a =设置为第9行传递的等式,然后传递abs(a * a-x)。我试着用最好的方式描述它对我来说这是一个稍微新的话题,我只是不确定这是否只能找到完美的根或者我的代码/方程是不正确的。
1 #include <cmath>
2 #include <iostream>
3 using namespace std;
4
5 double newtroot(double x, double a) {
6 if (fabs(a*a - x) <= DBL_EPSILON)
7 return a;
8 else
9 return newtroot(x, fabs(a*a + x)/(2*a));
10 }
11
12 int main() {
13 cout << newtroot(9, 1) << endl;
14 system("pause");
15 return 0;
16 }
编辑:该功能不仅适用于完美的正方形,而且只能正确返回完美的正方形。如果它不是一个完美的正方形a
最终是正确的值(在调试器中检查),但递归永远不会停止。我认为它必须是第6行中的比较,所以我尝试用a
替换DBL_EPSILON并返回错误的值。
当输入非完美正方形时,此错误也会在第6行显示:
RecursionProgrammingExcercisesMurphyT.exe中0x00007FFE8E9C06F0(ucrtbased.dll)的未处理异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001,0x00000013B2603FE8)。发生
答案 0 :(得分:0)
未检测到基本情况是由于过于乐观的解释:
DBL_EPSILON
不是“适合终止改进任何近似值的值,”但是
1和最大值之间的差值,大于1,可表示:
它需要缩放以限制相对错误
return (fabs(approx*approx - x) <= 2*x*DBL_EPSILON) ? approx
: newtroot(x, fabs(approx*approx + x)/(2*approx));
当一个近似值足以容忍数值误差时,一种有希望的终止它的方法是检查新的近似值既不是当前值也不是前一个值。
/*! approximate the value of x**.5 */
double newtroot(double x, double approx, double previous) {
double next = fabs(approx*approx + x)/(2*approx);
return next == approx || next == previous
? approx : newtroot(x, next, approx);
}