[英]C++ Square Root with recursion
由于某种原因,我的平方根程序得到的答案与大多数输入应该得到的结果略有不同。 我不确定为什么会这样。 只有某些输入是错误的。 在给出答案之后,我也在最后得到了一个分段错误,并且不确定为什么会这样。
#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;
}
该函数具有未定义的行为,因为您忘记放置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 );
你得到了崩溃,因为你试图访问argv[argc]
,它已经过了argv
数组的末尾。
您的数字可能已关闭,因为您正在与FLT_EPSILON
进行比较,后者是float
值。 DBL_EPSILON
用于双打。 但是,与其中任何一个相比,这不是解决此问题的正确方法。 您需要检查相对于您a
值缩放的差异。
我看到应该先修复的两个基本错误:
你的主要功能没有回报。 你应该放回return 0;
在最后一个主要功能结束时}
。
您正在尝试访问不存在的argv[argc]
。 该数组中最后一个现有元素是argv[argc - 1]
。 尝试更改循环语句,以便它不会尝试读取数组中不存在的部分。
添加到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的平方根。 这是一个残酷的精确度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.