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
}
}
}
这是我做过的平方根函数,它对一些数字有效,但对另一些,它只是空白,什么都不返回,我哪里搞错了?
2条答案
按热度按时间cygmwpex1#
您的代码中有几个问题,第一个问题是,当您试图为(* 可能 *)无理数。2虽然双精度浮点数不具有无限的精度,我当然不建议将该函数计算到那么高的精度。解决方法是添加某种“precision”或“epsilon”值(正如下面的评论中提到的)。或者当
increment
变得太小时跳出循环更好(正如@Pete Becker建议的):当然,您可以使用标准库,使用
std::sqrt
来执行此操作,但我假设您这样做是为了好玩。如果你对其他平方根算法感兴趣,Wikipedia上有一些看起来很吓人的算法。
我个人比较喜欢的一个函数是Newton's Method,但它是用来求函数的根的,我把它应用到平方根函数中,这个平方根函数是从here复制并修改而来的:
pb3skfrl2#
我主要关心的是
prec = 1;
和sqrt += prec
,因为一旦sqrt
是一个很大的数,表达式sqrt += prec
就不会以任何方式改变sqrt
,因为舍入和你的for循环会卡住...因此,您应该了解起始
prec
值,以及prec *= 0.1;
的精度应该增加多少倍对于数
|x|>1
,我们现在sqrt(x)
的大小具有int(x)
所需的整数位的一半,因此我们可以从中导出prec
log2
不需要是真实的log2
,您可以简单地取指数并将其除以2,然后将y构造为:例如,对于
(|x|<=1)
,以以下内容开头:prec = 0.5
现在,您缺少的结束条件是一旦
sqrt
停止变化就停止,例如:我也没有看到任何标志处理(你知道的情况下
x<0
)有关详细信息,请参阅: