2016-11-19 120 views
1

由于某种原因,我的平方根程序得到的答案与大多数输入所得到的答案略有不同。我不确定这是为什么。只有某些输入是错误的。在给出答案之后,我也会在最后得到一个分段错误,但我不确定这是为什么。C++递归平方根

#include<iostream> 
#include<cmath> 
#include<cfloat> 
#include<string> 
#include <cstdlib> 
using namespace std; 

//declare sqroot function calls recursive function newton 
double sqroot1(double num); 
double newton(double num, double guess); 
int main(int argc, char **argv) 
{ 

    for(int i = 0 ; i < argc ; i++) 
    { 
     cout<<"sqroot("<<argv[i+1]<<") is "<< sqroot1(atoi(argv[i+1]))  <<endl; 
    } 
} 

double newton(double num, double a) 
{ 
    if ((abs(a*a - num) <= FLT_EPSILON)) 
    { 
     return a; 
    } 
    else 
    { 
     newton(num, (a+num/a)/2); 
    } 
} 

double sqroot1(double num) 
{ 
    double sqrt = newton(num,num/2); 
    return sqrt; 
} 
+0

启用所有警告并查看编译器告诉您什么。然后看[为什么使用命名空间标准被认为是不好的练习?](http://stackoverflow.com/q/1452721/995714) –

+0

什么是一些值不好的平方根,你得到什么值? – 1201ProgramAlarm

回答

2

的功能未定义的行为,因为你忘了把return语句

double newton(double num, double a) 
{ 


    if ((abs(a*a - num) <= FLT_EPSILON)) 
    { 
     return a; 
    } 
    else 
    { 
     newton(num, (a+num/a)/2); 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    } 


} 

必须有

return newton(num, (a+num/a)/2); 
1

你得到的崩溃,因为您尝试访问argv[argc],这已经超过了argv阵列的末尾。

您的号码很有可能是因为您正在与FLT_EPSILON比较,这是float的值。 DBL_EPSILON用于双打。不过,与这两者中的任何一个比较都不是这个问题的正确方法。您需要检查相对于您的a值的比例差异。

0

我看应该首先固定两个基本错误:

  1. 你的主要功能没有回报。您应该在最后的}之前将return 0;放在主要功能的末尾。您正尝试访问不存在的argv[argc]。该阵列中最后一个存在的元素是argv[argc - 1]。尝试更改循环语句,以便它不尝试读取数组中不存在的部分。

0

添加到1201ProgramAlarm的答案,为什么以下这么糟糕?

if ((abs(a*a - num) <= eps)) 

比方说eps是1e-15,比DBL_EPSILON大一点。那么,如果a甚至是中等大(类似于5或更大),那么a*a的最后一位(ulp)中的单位大于eps,且条件只有在a*a == num时才为真。有一个风险,四舍五入,这将不会达到,你最终无限递归和崩溃。

现在,让我们说,num非常小,使得对于初始猜测

abs(num/2*num/2 - num) <= eps 

因此,举例来说,sqroot1(1E-20)将评估

abs(1e-40/4 - 1e-20) <= 1e-15 

这是真实的,你会得到5e-21作为1e-20的平方根。这是非常精确的。