当递归函数在javascript中可数时,最大调用堆栈大小超过RangeError

时间:2018-06-05 15:43:40

标签: javascript recursion max callstack

我创建了一个脚本,用于将数字除以所选的小数位数。除非我设置了大量的小数位,否则一切正常。当十进制数组长度达到~2400时,通过Node.js运行的文件放弃,Chrome放弃~1900。

我简化了我的代码,下面的脚本示例在Maximum call stack size exceeded十进制数组长度上抛出~20000 RangeError。我认为当循环或递归函数被无休止地调用时抛出此错误,但在我的情况下,有相当数量的迭代。它可能是一个庞大的数字,但我的模块旨在对大数字进行数学运算。

为什么会发生这种情况?我可以避免发生这种RangeError吗?

var decimals = [];
var max = 20000;

recurse();

function recurse() {
  decimals.push(Math.floor(Math.random()*10));
  if(decimals.length === max) return;
  recurse();
}

3 个答案:

答案 0 :(得分:2)

不,您可以对调用堆栈进行多少函数调用是有限制的,因此即使您的递归函数具有可访问的基本情况,如果递归调用的数量太大,它仍将抛出错误。

一种解决方法是使用名为trampoline的技术,您不在函数内部直接执行递归调用,但是insted返回一个新函数,然后在循环中执行,直到基本情况为止到达。

使用这种技术,您的函数可以执行任意数量的递归调用,因为您不会同时将更多这些函数调用放入调用堆栈,因此它不会溢出。



var decimals = [];
var max = 20000;

function _recurse(){
  decimals.push(Math.floor(Math.random()*10));
  if(decimals.length === max) return;
  return () => _recurse();
}

const trampoline = fn => (...args) => {
  let res = fn(...args);
  while (typeof res === 'function') { res = res(); }
  return res;
}

const recurse = trampoline(_recurse);

recurse()

console.log(decimals);




请注意,使用循环可以在不使用递归的情况下以更简单的方式解决问题。例如:



function createRandomSequence(amount) {
  const decimals = [];
  for (let i = 0; i < amount; i++) {
    decimals.push(Math.floor(Math.random()*10));
  }
  return decimals;
}

console.log(createRandomSequence(10));
&#13;
&#13;
&#13;

答案 1 :(得分:2)

只需使用常规循环,或类似:

 const random = length => Array.from({ length }, () => Math.floor(Math.random() * 10));

const decimals = random(20000);

答案 2 :(得分:1)

关于调用堆栈:请参阅this web page

如果它是你所追求的20,000(伪随机)小数,你也可以使用类似的东西:

var maxDecimals = 20000;
var decimals = Array.from({length: maxDecimals})
  .map(v => Math.floor(Math.random()*10));
  
console.log(decimals);