首页 > 解决方案 > 使用带有递归 c# 的牛顿法的平方根

问题描述

我正在尝试计算数字 12345 的平方根。我是编程新手,需要底部帮助,所以我没有收到异常“堆栈溢出”。

public static decimal Sqrt(int number, decimal root)
{
    return Sqrt(number, root - ((root * root) - number) / (2 * root));
}

static void Main(string[] args)
{

    decimal root = Sqrt(12345, 10M);

    Console.WriteLine(root);

}

标签: c#recursion

解决方案


维基百科

堆栈溢出的最常见原因是过深或无限递归,其中函数调用自身的次数太多,以至于存储与每次调用相关的变量和信息所需的空间超出了堆栈的容量。

C中无限递归的一个例子。

int foo()
{

    return foo();

}

函数 foo 在调用时会继续调用自己,每次都会在堆栈上分配额外的空间,直到堆栈溢出导致分段错误。然而,一些编译器实现了尾调用优化,允许特定排序的无限递归——尾递归——发生而没有堆栈溢出。这是因为尾递归调用不占用额外的堆栈空间。

你错过了一张支票。您的代码是无限递归的,因为没有办法摆脱递归。

线

return Sqrt(number, root - ((root * root) - number) / (2 * root));

将导致另一个Sqrt方法调用,它会导致另一个Sqrt方法调用,这将导致 .... SO 当它停止并返回正确的结果?!

无论如何,如果您添加一个 if 语句,它将正常工作。

public static decimal Sqrt(int number, decimal root)
{
    if (Math.Abs(root * root - number) <= 0.00000000001M)
        return root;

    return Sqrt(number, root - ((root * root) - number) / (2 * root));
}

// Usage:
static void Main(string[] args)
{
    Console.WriteLine(Sqrt(4, someDecimal));
}

如果你使用

if (root * root == number)

代替

if (Math.Abs(root * root - number) <= 0.00000000001M)

,您的代码将只支持完美的正方形。


推荐阅读