在C++中实现平方根函数不起作用

oknrviil  于 2022-11-27  发布在  其他
关注(0)|答案(2)|浏览(156)
double _sqrt(double n)
{
    double sqrt = 0, c = 0, prec = 1;

    for (;; sqrt += prec) //increments sqrt per precision
    {
        c = sqrt * sqrt;
        if (c == n)
        {
            return sqrt;
        }
        if (c > n) // if square is greater then..
        {
            sqrt -= prec; // decrement squareroot by previous precision
            prec *= 0.1; // increase precision eg. 1, 0.1, 0.01, 0.001 .....INF
        }
    }
}

这是我做过的平方根函数,它对一些数字有效,但对另一些,它只是空白,什么都不返回,我哪里搞错了?

cygmwpex

cygmwpex1#

您的代码中有几个问题,第一个问题是,当您试图为(* 可能 *)无理数。2虽然双精度浮点数不具有无限的精度,我当然不建议将该函数计算到那么高的精度。解决方法是添加某种“precision”或“epsilon”值(正如下面的评论中提到的)。或者当increment变得太小时跳出循环更好(正如@Pete Becker建议的):

double _sqrt(const double& n)
{
    const double precision = 0.000001;
    double increment = 1.0, sqrt = 0.0;

    while (true)
    {
        if (increment <= precision)
            break;
        else if (sqrt * sqrt > n)
        {
            sqrt -= increment;
            increment *= 0.1;
        }
        else 
            sqrt += increment;
    }

    return sqrt;
}

当然,您可以使用标准库,使用std::sqrt来执行此操作,但我假设您这样做是为了好玩。
如果你对其他平方根算法感兴趣,Wikipedia上有一些看起来很吓人的算法。
我个人比较喜欢的一个函数是Newton's Method,但它是用来求函数的根的,我把它应用到平方根函数中,这个平方根函数是从here复制并修改而来的:

double _sqrt(const double& n)
{
    const double precision = 0.00001;
    double sqrt, x = n;

    while (true)
    {
        sqrt = 0.5 * (x + (n / x));

        if (std::abs(sqrt - x) < precision)
            break;

        x = sqrt;
    }

    return sqrt;
}
pb3skfrl

pb3skfrl2#

我主要关心的是prec = 1;sqrt += prec,因为一旦sqrt是一个很大的数,表达式sqrt += prec就不会以任何方式改变sqrt,因为舍入和你的for循环会卡住...
因此,您应该了解起始prec值,以及prec *= 0.1;的精度应该增加多少倍
对于数|x|>1,我们现在sqrt(x)的大小具有int(x)所需的整数位的一半,因此我们可以从中导出prec

y = log2(|x|)
prec = y*0.1

log2不需要是真实的log2,您可以简单地取指数并将其除以2,然后将y构造为:

y = 2^((exponent_extracted_from_x>>1)+1)

例如,对于(|x|<=1),以以下内容开头:prec = 0.5
现在,您缺少的结束条件是一旦sqrt停止变化就停止,例如:

...
for (sqrt0=sqrt-prec; sqrt!=sqrt0; sqrt0=sqrt,sqrt+=prec)
 {
 ... your original code ...
 }
return sqrt;
}

我也没有看到任何标志处理(你知道的情况下x<0
有关详细信息,请参阅:

相关问题