通过递归检查均匀性(雄辩的javascript练习)

通过递归检查均匀性(雄辩的javascript练习),javascript,recursion,Javascript,Recursion,我已经开始阅读有说服力的Javascript,这里有一个关于生成递归函数以检查均匀性的练习。 我用了几种不同的方法,很简单,但由于某种原因,我不能再用负数来处理它了。我让它工作,然后可能意外地改变了一些东西,现在它只对积极的方面起作用 你能告诉我为什么这个代码是错误的吗 (textfield.append只是将一些内容打印到我在html/css文档中创建的textfield中,这样我就可以将练习保存在某种“程序”中。) 功能检查(n){ 如果(n==0){ $('#textfield')。追加(

我已经开始阅读有说服力的Javascript,这里有一个关于生成递归函数以检查均匀性的练习。 我用了几种不同的方法,很简单,但由于某种原因,我不能再用负数来处理它了。我让它工作,然后可能意外地改变了一些东西,现在它只对积极的方面起作用

你能告诉我为什么这个代码是错误的吗

(textfield.append只是将一些内容打印到我在html/css文档中创建的textfield中,这样我就可以将练习保存在某种“程序”中。)

功能检查(n){
如果(n==0){
$('#textfield')。追加('Even');
}
如果(n==1 | | n==1){
$('#textfield')。追加('不均匀');
}
否则{
如果(n>1){
n-=2;
均匀检查(n);
}
如果(n<-1){
n+=2;
均匀检查(n);
}
}
}
我知道它可以写得更短,我做了一个更短的形式,但这对负片也不起作用


我知道问题是堆栈溢出,但为什么会发生这种情况?

您的代码似乎可以工作,除了大的数字。用-12或10之类的东西试试就可以了。输入30000时,它会自动挂起。可能是因为递归调用该方法的次数太多

const
inputElement=document.getElementById('number-input'),
checkTrigger=document.getElementById('check-number')
resultLog=document.getElementById('result');
功能检查(n){
如果(n==0){
resultLog.textContent=`${n}是事件。`;
}
如果(n==1 | | n==1){
resultLog.textContent=`${n}不均匀。`;
}
否则{
如果(n>1){
n-=2;
均匀检查(n);
}
如果(n<-1){
n+=2;
均匀检查(n);
}
}
}
函数checkInputNumber(事件){
常数
numberToCheck=parseInt(inputElement.value);
均匀检查(数字检查);
}
checkTrigger.addEventListener('click',checkInputNumber);
$(“#evenrecursive”)。单击(function(){($(“#textfield”)。追加(“

新命令:检查数字是否为偶数。

”);var n=prompt('pick a number',”);evencheck(n);})
#{
边框:1px实心;
最小高度:20px;
宽度:100%;
}

检查

单击我获取提示。
现在它只适用于积极因素。为什么会这样

您可能正在传递一个字符串,在这种情况下,
n+=2
执行字符串连接而不是数字相加(而
-=2
始终转换为数字)。尝试添加

if (typeof n != "number") throw new TypeError("n must be a number");
在函数的第一行中,如果从用户处获取字符串输入,请确保使用。

不是答案,而是扩展注释

上面的代码可能会更快,因为编译器可以将其优化为:

function evencheck(n){
  while(true){
    if (n == 0){
      return $('#textfield').append('Even');
    }
    if (n == 1 || n == -1){
      return $('#textfield').append('Uneven');
    }        
    n = n>1? n -2 : n+2;
  }
}
因此,您没有填充函数堆栈(可能是非常大的数字),而且它实际上非常快


你说它不适用于底片是什么意思?因为它对我有用,只是不起作用;chrome和firefox都不起作用;chrome给了我一个
未捕获的范围错误:超过了最大调用堆栈大小
-错误,firefox只是有点冻结了几秒钟。@ArthurVanhoorebeke在什么输入上?顺便说一句,“不均匀”被称为“奇数”:-)事实上-我会在
-5
的输入上把它改为奇数:-)。即使是非常小的数字,在我为它制作的页面中也不起作用。是的,它在这里起作用。。。谢谢但在我的页面中不起作用。下面是我在页面上显示的方式:
$('#evenrecursive')。单击(function(){$('#textfield')。追加(

新命令:检查数字是否为偶数。

”;var n=prompt('pick a number','');evencheck(n);)。这有什么问题吗?无论如何,很高兴知道代码本身是有效的:)谢谢。我不认为提示符的结果是数字类型的,它很可能返回一个字符串。然后,由于类型强制,这不重要。将
prompt('pick a number')
更改为
number(prompt('pick a number'))
。现在它适用于负片。“-”肯定是没有被强制输入到某个数字的东西我猜。。。我真傻,竟然忽略了。。。谢谢刚才对发生的原因进行了解释,很高兴听到你自己也发现了这一点。问题解决了,确实是类型胁迫。哑巴被我忽视了。我将
prompt(…)
更改为
Number(prompt…)
。解决:D.谢谢@亚瑟王很高兴能帮上忙,你可能想把答案做完!我不能投票,我没有15个代表。。。答案被接受,谢谢!智能优化:)这是一个很棒的解决方案。两个观察结果:1)Chrome中的JS引擎没有优化代码,这完全取决于你。2) 不要忘记添加一个
break
而不是
return
,否则您将等待很长时间,等待该方法停止运行。除此之外,它还可以确定一个数字对于较大的数字是奇数还是偶数。@thijs你为什么知道这一点?唯一简单的检查方法是使用两个不同版本的chrome运行代码并检查时间差。2) 不,如果返回,则无需中断。@Jonasw我知道Chrome没有优化该方法,因为在Chrome v60中运行第一个实现时,我得到了一个“超出最大调用堆栈大小”错误,但当
n
为300000时,第二个实现没有问题。第二点是我的错误,将jQuery代码替换为
console.log
,并错误地删除了前面的
return
function evencheck(n){
    if (n == 0){
      return $('#textfield').append('Even');
    }
    if (n == 1 || n == -1){
      return $('#textfield').append('Uneven');
    }        
    return evencheck(n > 1? n-2 : n+2);
}
function evencheck(n){
  while(true){
    if (n == 0){
      return $('#textfield').append('Even');
    }
    if (n == 1 || n == -1){
      return $('#textfield').append('Uneven');
    }        
    n = n>1? n -2 : n+2;
  }
}