如何使用递归函数替换while循环?

3
我使用 while 循环的方法如下:
while (value < -180 || value > 180) {
  if (value < -180) {
    value += 360
  }
  if (value > 180) {
    value -= 360
  }
}

我想使用递归函数而不是while。我在谷歌上搜索过,但没有找到任何相关信息。因此,我认为也许我可以在这里得到答案。


2
为什么要使用递归?除非问题特别适合递归解决方案,否则递归可能会妨碍您的程序。 - Carcigenicate
1
@Carcigenicate 我因个人原因想避免使用 while - alex
1
我鼓励你仔细考虑那些个人原因。每种工具都有其适用的场合。 - Carcigenicate
@user151841 我同意学习递归很重要,如果这只是一个练习,那就很好。我只是在警告不要仅仅为了使用递归而使用它。 - Carcigenicate
1
正如@Carcigenicate所指出的那样,递归可能会妨碍您的程序。通常情况下,未被解释器/编译器优化(未转换为“while”循环)的递归通常更昂贵、更慢,并包含固有的堆栈溢出风险。很高兴您正在学习递归,但您也应该了解它的风险和限制。 - Myst
显示剩余5条评论
2个回答

5

将明确的循环转换为递归解决方案的“通用公式”如下:

  • 确定循环中的“累加器”。通常,循环将操作一到两个值,这些值是循环的“结果”。

  • 将累加器作为函数的参数。

很难概括任何旧的循环如何替换为递归,但这可以用作一般指南:

对于具有以下形式的循环:

var a, b, c = ...;

while (condition) {
   // Change a, b, c...
}

// Use a, b, c

您可以将其转换为:
function recursive(a, b, c...) {
   // When the condition does *not* hold, end the recursion.
   // Note that condition is negated relative to the while-loop.
   if (!condition) {
      // Base case.
      return [a, b, c...];

   } else {
      // Change a, b, c...
      //  and recurse with the new values
      return recursive(a', b', c'...);
   }
}

对于你的例子,这将看起来像这样:
function recur(value) {
  if (value > -180 || value < 180) {
    return value; // Base case

  } else if (value < -180) {
    return recur(value + 360);

  } else {
    return recur(value - 360);
  }
}

在你需要再次循环的情况下,递归运用,但需要记住必须返回递归的结果。而在想要结束循环的情况下,需返回累加器。注意每个执行分支都必须以一个返回结束。只要你放弃递归的结果(未返回)就会导致数据丢失。
请注意:
如我在评论中提到的那样,递归不是应该用于任何问题的通用方法,尤其是当语言不支持优化时。它可能适用于小问题,但是在问题变得更大时,你可能会发现它突然开始引起“堆栈溢出”的问题。
当处理可变数据时,递归可能会变得困难和令人困惑。如果你的累加器是可变的(列表、映射或任何其他非原始数据类型),则必须非常小心地设置所有内容。相同的数据将能够从每个递归分支进行访问和更改。如果你不小心,则会以很难调试的方式更改你的累加器。如果你想走递归/函数式路线,我建议你查看像Immutable.js这样的库,或者类似Clojurescript这样几乎只涉及不可变结构的语言。Clojurescript可以编译成JavaScript。

谢谢提供示例。但我想要一个递归函数,可以应用于任何需要使用while的情况,而不仅仅是我的示例。 - alex
1
@alex 递归很难像那样概括; 这就是为什么我在答案开头包含了那个列表。不过我会尝试写一个通用的“蓝图”。 - Carcigenicate

2

试试这个:

var recur_num = recursion(500)
console.log(recur_num)

var while_num = viaLoop(500)
console.log(while_num)

function recursion(value) {
  
  if (value < -180) {
    return recursion(value + 360);
 } 
  
  if(value > 180){
    return recursion(value - 360);
  }
  
   if (value > -180 || value < 180) {
    return value; 
  }
}


function viaLoop(value){

while (value < -180 || value > 180) {

 if (value < -180) {
    value += 360
  }
   
  if (value > 180) {
    value -= 360
  }
}

return value;
}

您可以比较递归版本的值和while循环版本的值。

请告诉我您是否有任何疑虑? - user8233884

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