【问题标题】:Why this function return is not returning expected results in Java?为什么这个函数 return 在 Java 中没有返回预期的结果?
【发布时间】:2021-02-14 09:57:13
【问题描述】:

下面是一个接受 int 并返回 int 的函数。在函数内我调用函数本身,如果 i==1,我想退出我的函数。

基本上我正在尝试以递归方式计算阶乘。

代码片段

static int factorial(int i){
   result = result * i;
   if(i==1){
       return 0;
   }
   factorial(i-1);
   return 1;
}

注意 - result 是一个全局 int 变量并初始化为 1。

为什么这个函数返回 1 而不是 0。 [注意当 i==1 时,返回语句指针应该从函数中出来]

请不要发布更好的阶乘算法,我正在寻找 - 为什么这段代码的行为有点不同。

【问题讨论】:

  • result 无处定义
  • @azro 注意 - 结果是一个全局 int 变量并初始化为 1。
  • 我投票结束这个问题,因为 OP 应该花几周时间学习如何编写和调试 java。
  • 投票结束,学生需要学习更好的调查策略。 ;)

标签: java


【解决方案1】:

您的代码甚至无法编译,因为 result 未定义。

那么,方法可以返回01,与您编写的return无关,因此您不能指望得到真正的值。


然后是真正的算法

  • 对于01,返回1
  • 否则返回乘以factorial(previous)的值
static int factorial(int i) {
    if (i <= 1) { // for 0 or 1
        return 1;
    }
    return i * factorial(i - 1);
}

【讨论】:

  • 他说结果是一个全局变量。他只是好奇他的代码sn-p的返回值。他可能正在使用该全局变量来获取阶乘。
  • @BeshambherChaukhwan 没关系,OP 首先不应该使用全局变量。这是唯一正确的答案。
  • @luk2302 我尊重你对正确用法的看法......但是感谢社区,我解决了我的递归疑问。[至少我得到了提示]
【解决方案2】:

调用factorial(3)的示例:

int i = factorial(3);
    +--------------------------------------------------+
    |result = result * 3;                              |
    |if (i==1) {                                       |
    |  // not executed                                 |
    |}                                                 |
    |factorial(2);                                     |
    |    +-------------------------------------------+ |
    |    |result = result * 2;                       | |
    |    |if (i==1) {                                | |
    |    |  // not executed                          | |
    |    |}                                          | |
    |    |factorial(1);                              | |
    |    |    +---------------------------------+    | |
    |    |    |result = result * 1;             |    | |
    |    |    |if (i==1) {                      |    | |
    |    |    |  return 0;                      |    | |
    |    |    |// nothing more in factorial(1)  |    | |
    |    |    +---------------------------------+    | |
    |    |// factorial(1) returned 0 (value not used)| |
    |    |return 1;  // factorial(2)                 | |
    |    +-------------------------------------------+ |
    |// factorial(2) returned 1 (value not used)       |
    |return 1;  // factorial(3)                        |
    +--------------------------------------------------+
i = 1; // the value returned by last call

factorial(3) 返回 1! 递归被return 0终止,但该值未被使用

如果最后两行连接到return factorial(i-1);,则会返回零


只有 factorial(1) 会返回 0,例如int i = factorial(1)

【讨论】:

  • 非常感谢,现在我知道我哪里错了
【解决方案3】:

因为你没有返回 0。你的函数将始终返回 1,这是第一次调用的返回值。正在进行所有其他递归函数调用,但未用于由父函数返回。例如,如果您调用 factorial(5),那么所有重复调用(从 4 到 1)都将执行并处理“结果”变量,但您只会得到 factorial(5) 的返回值,该值始终为 1。

【讨论】:

  • hii 感谢您的快速回复....但是看看如果 i==1 然后使用 return 语句,函数不应该超出函数范围
  • 请调试这段代码......你会明白我想说什么!
  • 是的,但您会看到检查函数返回值的区域与最后一次函数调用无关。您的 main 函数仅与第一个函数调用进行通信,即 factorial(5) 不使用其子循环函数值作为返回值,因此您的主代码将永远不会看到 return 0 只有函数调用 factorial(2) 可以看到阶乘 (1) 给出 0
  • 您在使用全局变量“result”背后的想法应该是首先不要理会返回的值。如果您从结果变量中获取阶乘,那么无论函数返回什么,您都将始终在结果中具有所需的值
  • 所以你的意思是阶乘(1)返回0只对阶乘(2)可见,而不是主函数..对吗?
【解决方案4】:

您的代码的根本问题是它对返回数据的方式感到困惑。

你有一个result 全局变量,它应该是这个函数“传达”答案的方式,但它有一个返回值。它们听起来完全不同(一个是变量,一个是语言结构),但它们在这里用于相同的目的。你一半的时间返回,一半的时间你设置result,这会导致你的代码产生你正在观察的效果。

解决方案是选择一方。 only 使用result - 将方法更新为具有void 返回值,并且不要使用return x; 语句(仅return;)。或者,完全摆脱result,并使用return 进行通信。

if(i==1){
          return 0;
      }

取这一行并与下一行进行比较:

factorial(i-1);

这一行调用factorial 函数并抛出它返回的任何东西,因为你没有在任何地方分配它。这就是为什么您无法观察到您正在返回的 0:因为您忽略了它。

在我看来,您认为return 0; 以某种方式设置了result,或者result 持有“无论函数返回什么”,但事实并非如此。它们是不同的东西。

【讨论】:

  • “解决方案是选择一边。” - 老实说,解决方案是不使用全局变量来保持任意状态,factorialvoid闻起来很臭。
猜你喜欢
  • 2017-12-22
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2018-10-30
  • 2013-03-25
  • 1970-01-01
相关资源
最近更新 更多