繁体   English   中英

带递归的C ++ Square Root

[英]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值缩放的差异。

我看到应该先​​修复的两个基本错误:

  1. 你的主要功能没有回报。 你应该放回return 0; 在最后一个主要功能结束时}

  2. 您正在尝试访问不存在的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM