Pow(x,y)函数的工作流程是什么?

4

我正在学习C#,通过“sololearn”和udemy课程进行学习。我在完成挑战时遇到了困难,无法弄清楚下面的代码为什么生成32(即32是正确答案,我想知道为什么),有人能解释一下这个过程吗?我认为调用自身的方法让我感到困惑。

static double Pow(double x, int y)
{
    if (y == 0)
    {
        return 1.0;
    }
    else
    {
        return x * Pow(x, y - 1);
    }
}

static void Main()
{
    Console.Write(Pow(2, 5));
} 

请忽略我糟糕的代码。我尝试在移动设备上完成它,这很困难,答案是32。可以有人解释一下吗?
编辑:抱歉,这是我处理它的方法。将2和5传递给Pow,检查是否为y == 0,这是错误的,现在是y == 5,因此x * pow(x, y-1)公式将被激活。X仍然是2,y现在是4,这意味着它再次未能通过检查,直到返回1.0结束。X保持在2不变,所以2 * 1.0 = 2而不是32?

4
你到底在这里不明白什么?我希望你知道什么是方法,返回值和静态无返回类型的主函数。话虽如此,你遇到什么困难还是不太清楚。 - MakePeaceGreatAgain
4
请重新考虑您问题的标题。标题应该简要说明您所遇到的问题。目前的标题不够好。 - Silvermind
1
如果你查找“递归”,你可能会得到“看到递归”,但也有更有帮助的解释。 - Jeroen Mostert
1
这是一个递归方法。在GeeksForGeeksWikipedia上了解更多关于递归的知识,或者在互联网上搜索“递归”,有很多好的资源。 - Yeldar Kurmangaliyev
1
是的,最内部的调用返回1,而外部的调用返回2。但是下一个外部调用然后返回x * 2,即4等等,直到你拥有32。 - MakePeaceGreatAgain
显示剩余4条评论
5个回答

9

首先需要注意的是,这不是通常实现幂函数的方式。这样做是为了演示递归。

既然说明了这一点,让我们看看调用 Pow(2, 5) 时会发生什么:

Pow(x = 2, y = 5)
    -> return 2 * Pow(2, 4)
<- 2 * 16 = 32

  Pow(x = 2, y = 4)
      -> return 2 * Pow(2, 3)
  <- 2 * 8 = 16

    Pow(x = 2, y = 3)
        -> return 2 * Pow(2, 2)
    <- 2 * 4 = 8

      Pow(x = 2, y = 2)
          -> return 2 * Pow(2, 1)
      <- 2 * 2 = 4

        Pow(x = 2, y = 1)
            -> return 2 * Pow(2, 0)
        <- 2 * 1 = 2

          Pow(x = 2, y = 0)
              -> return 1 (because y == 0)
          <- 1

要阅读这个递归调用栈的表示方式,请从上到下查看参数如何改变;然后从下到上查看返回值(我用 <- 标识)。


8

好的,让我们来看看整个过程。

首先,静态函数是一种可以在不实例化对象的情况下调用的函数。所有同一类的对象共享一个签名。“double”是C#中的一个类型,在这里出现是为了显示函数的最终输出类型。Pow是函数的名称,“double x”和“int y”是根据它们的类型描述的参数(名称不太恰当,但我们将把它留到另一天再说)。

所以x是一个数字,y是该数字的幂。这里有一个条件检查两种结果。如果y为0,则答案始终为1,是简单的数学计算。否则,函数使用递归执行算术运算(它再次调用自身,直到满足终止条件)。我们得到32的原因是因为2x2x2x2x2=32。它是2的5次方。

我假设您知道main和console.write是什么。


7
该方法基本上计算了“xy次方”。 它以递归方式进行计算。
首先,它定义了一个基本情况:任何数的0次方都是1。
然后,它定义了在所有其他情况下该做什么:x * Pow(x, y - 1)。 假设y很大,那么x * Pow(x, y - 1)等于什么?它是x * x * Pow(x, y - 2),这又是x * x * x * Pow(x, y - 3)。 看到模式了吗? 最终,您将达到第二个参数y - N为0的地方,正如我们所确定的那样,这是1。此时,我们有多少个x *?恰好是y
让我们看一下Pow(2,5)的实际操作:
Pow(2, 5)
2 * Pow(2, 4)
2 * 2 * Pow(2, 3)
2 * 2 * 2 * Pow(2, 2)
2 * 2 * 2 * 2 * Pow(2, 1)
2 * 2 * 2 * 2 * 2 * Pow(2, 0)
2 * 2 * 2 * 2 * 2 * 1

因此结果为32。

2

你好,这里是递归算法,它会重复执行直到y=1,然后返回2,接着返回4、8、16、32,最终结果是2^5=32


1
为了能够理解这个递归行为中的每一个操作,需要记录所有细节以查看实际情况。例如:
using System;
namespace Tester
{
    class test 
    {
        // What Pow actually does:
        static double logPow(double x, int y) {
            var old = x; // Hold the x
            for (var i = 0; i < y; i++){ // do it y times
                x = old * x; // Multiply with it's first self
            }
            return x;
        }
        static int counter = 0;
        static double Pow(double x, int y) {
            counter++;
            Console.Write("Recursive action[" + counter + "] Y status ["+ y +"] : ");
            if (y == 0)
            {
                Console.Write("return 1.0 = " + logPow(x, y) + " \n");
                return 1.0;
            }
            else
            {
                Console.Write("return " + x + " * Pow(" + x + ", " + y + " - 1) = " + logPow(x,y-1) + " \n");
                return x * Pow(x, y - 1);
            }
        }
        static void Main() {
            Console.Write("Last Result : " + Pow(2, 5)); 
        }
    }
}

这将得到结果:

Recursive action[1] Y status [5] : return 2 * Pow(2, 5 - 1) = 32 
Recursive action[2] Y status [4] : return 2 * Pow(2, 4 - 1) = 16 
Recursive action[3] Y status [3] : return 2 * Pow(2, 3 - 1) = 8 
Recursive action[4] Y status [2] : return 2 * Pow(2, 2 - 1) = 4 
Recursive action[5] Y status [1] : return 2 * Pow(2, 1 - 1) = 2 
Recursive action[6] Y status [0] : return 1.0 = 2 
Last Result : 32

您可以通过查看这些详细信息来调试代码。 同时,您可以使用此链接进行娱乐:https://onlinegdb.com/Bysbxat9H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接