递归问题 - 希望获得特定于我的代码的建议

问题描述 投票:0回答:1

我过去曾尝试过询问与此问题相关的建议,并且我被告知问题的根源是“尾递归”。人们指示我切向相关的帖子,但我在将这些帖子中的建议应用到我的代码时遇到了麻烦。

有人可以解释一下我可以对我的代码进行的具体修改,以解决我遇到的递归问题(详见下文)?我花了好几个小时试图解决这个问题并且无处可去(noob here ...)。

所以,我的代码的一些背景:

这会在2到20之间生成2个不同的随机数:

function GenerateRandomNumber1to20No1() {
    var min = 2, max = 20;
    var random = Math.floor(Math.random() * (max - min + 1)) + min;   
    return random;

}

 var GenerateRandomNumber1to20No1 = GenerateRandomNumber1to20No1(); 
$('.GenerateRandomNumber1to20No1').html(GenerateRandomNumber1to20No1);

 function GenerateRandomNumber1to20No2() {
    var min = 2, max = 20;
    var random = Math.floor(Math.random() * (max - min + 1)) + min;   
  return (random !== GenerateRandomNumber1to20No1) ? random: GenerateRandomNumber1to20No2(); 

  ///////////HERE'S ONE PLACE WHERE RECURSION IS AN ISSUE, I BELIEVE //////////////

        }

 var GenerateRandomNumber1to20No2 = GenerateRandomNumber1to20No2(); 
$('.GenerateRandomNumber1to20No2').html(GenerateRandomNumber1to20No2);

这会生成2个不同于前2个数字的数字:

function GenerateRandomNumber1to20lessthanNo1() {
    var min = 2, max = GenerateRandomNumber1to20No1-1;
    var random = Math.floor(Math.random() * (max - min + 1)) + 1;   
    return random;

}

 var GenerateRandomNumber1to20lessthanNo1= GenerateRandomNumber1to20lessthanNo1(); 
$('.GenerateRandomNumber1to20lessthanNo1').html(GenerateRandomNumber1to20lessthanNo1);

function GenerateRandomNumber1to20lessthanNo2() {
    var min = 2, max = (GenerateRandomNumber1to20No2 - 1);
    var random = Math.floor(Math.random() * (max - min + 1)) + min;   
  return (random !== GenerateRandomNumber1to20lessthanNo1) ? random: GenerateRandomNumber1to20lessthanNo2();

}    
///////////HERE'S ANOTHER PLACE WHERE RECURSION IS AN ISSUE, I BELIEVE //////////////


var GenerateRandomNumber1to20lessthanNo2 = GenerateRandomNumber1to20lessthanNo2(); 
$('.GenerateRandomNumber1to20lessthanNo2').html(GenerateRandomNumber1to20lessthanNo2);

我使用这些变量来替换具有与其各自变量对应的类的元素。

<span class = "GenerateRandomNumber1to20nNo2"></span>
<span class = "GenerateRandomNumber1to20nNo2"></span>
<span class = "GenerateRandomNumber1to20lessthanNo1"></span>
<span class = "GenerateRandomNumber1to20lessthanNo2"></span>

例如,<span class = "GenerateRandomNumber1to20nNo2"></span>被替换为为变量GenerateRandomNumber1to20nNo2生成的数字。

有时代码工作正常:变量生成,元素被这些变量替换。其他时候,变量不会填充,我得到一个如下所示的错误:

Uncaught RangeError: Maximum call stack size exceeded
    at GenerateRandomNumber1to20lessthanNo2 

我被告知我收到此错误,因为我使用“尾递归”但我在将“尾递归”的研究应用于我的代码时遇到了麻烦。我在代码中指出了我认为递归是个问题的地方。

如果有人可以使用我的特定代码给我建议,我将非常感激。

javascript jquery html recursion tail-recursion
1个回答
0
投票
function GenerateRandomNumber1to20lessthanNo2() {
  var min = 2, max = (GenerateRandomNumber1to20No2 - 1);
  var random = Math.floor(Math.random() * (max - min + 1)) + min;   
  return (random !== GenerateRandomNumber1to20lessthanNo1)// <=== HERE
    ? random
    : GenerateRandomNumber1to20lessthanNo2();
}

想象一下你得到两个随机数的情况:2和3.现在,你试图滚动小于2和3的随机数,同时仍然使用2作为最低数字。

由于以下几个原因,你迷失在这些功能中:

  • 您正在使用函数返回的值覆盖函数...因此您的函数将变为值。这变得非常难以遵循。
  • 你有4个功能,基本上做同样的事情,但测试不同的情况,这使得这部分难以推理,因为它很容易眯眼,忘记你正在看哪一个(他们仍然是功能,还是他们的价值观在你看它们的时候)
  • 你有一些在逻辑上可行的边缘情况,你没有测试(这就是为什么你要进行无限递归,以及为什么你会遇到无限循环)

我将使用示例重构更新此内容。

function randomBetween (min, max) {
  var ceiling = max + 1;
  return Math.floor(Math.random() * (ceiling - min)) + min;
}

function randomBetweenAndExcluding (min, max, excluding) {
  var random;
  do {
    random = randomBetween(min, max);
  } while(random === excluding);
  return random;
}

var random1High = randomBetween(2, 20);
var random1Low = randomBetween(1, random1High - 1);
var random2High = randomBetweenAndExcluding(2, 20, random1High);
var random2Low = randomBetweenAndExcluding(1, random2High - 1, random1Low);

function addText (selector, text) {
  const el = document.querySelector(selector);
  if (el) { el.textContent = text; }
}

addText(".GenerateRandomNumber1to20nNo1", random1High);
addText(".GenerateRandomNumber1to20nNo2", random2High);
addText(".GenerateRandomNumber1to20lessthanNo1", random1Low);
addText(".GenerateRandomNumber1to20lessthanNo2", random2Low);
// PS you have a copy-paste error in your HTML classes, too
// the names are too long, and too similar, and already confused
// because of the overwriting functions with vars

在这个代码的情况下,random1Highrandom2Low完全可以接受相同的数字。如果这是不可接受的,如果滚动的数字是2, 1, 3,你将打开另一个无限循环的将死。如果这是不可接受的,那么你需要在3到20之间随机运行前两个数字,因此底部仍然有1和2的空间,并使排除功能更加有趣。

希望在这里看到移动的部件更容易。

如果你想像以前一样继续使用递归(一个函数调用自身,从内部),你可以定义第二个函数

function randomBetweenAndExcluding (min, max, exclude) {
  var random = randomBetween(min, max);
  return random === exclude
    ? randomBetweenAndExcluding(min, max, exclude)
    : random;
}

我通常更喜欢递归。递归的一个缺点是,如果在返回之前在太多函数内调用太多函数,通常会在数十到数百之间的某个地方,在有效代码中“打击堆栈”/命中“堆栈溢出”(同样的事情)是可能的。成千上万的电话,没有返回,但仍然)。因此,在无限递归的情况下,最终浏览器会抛出错误。无限的while循环的缺点是你的浏览器和页面锁定,循环永远不会停止运行,最终,也许,你的浏览器会弹出一些东西并说“哎;这肯定已经运行了很长时间;它看起来就像页面死了,你想要杀死它吗?“

© www.soinside.com 2019 - 2024. All rights reserved.