最大调用堆栈尺寸上汇聚一系列功能
问题描述:
我试图得到一个特定的收敛系列函数在JavaScript中摸索出超出错误:最大调用堆栈尺寸上汇聚一系列功能
function cnvg(sum,marker){
if((marker--||1000)>=0){
return cnvg(sum=(sum||0) + 1/Math.pow(-3,marker)/(2*marker+1), marker)
} else {
return sum;
}
}
我期待cnvg()
回来与Math.PI/Math.sqrt(12)
相当于(请参阅下面的图片),但我一直得到“最大调用堆栈大小超出”错误。我认为这可能是迭代的次数,所以我放弃1000
参考100
,然后10
,最后到1
,但我似乎仍然收到错误。
从理论上讲,一旦倒计数至0,并执行最后的循环,应立即停止,并返回sum
价值,但是这似乎并没有这样的情况?谁能告诉我我做错了什么?
在此先感谢。
答
当然
默认参数
在叶奥尔德次,我们写默认参数是这样
function add (x, y) {
if (x === undefined) x = 0
if (y === undefined) y = 0
return x + y
}
现在ES2015
,后来,我们就可以像这样写出来
function add (x = 0, y = 0) {
return x + y
}
让事情变得简单
递归过程可以简单地写为
const converge = (k = 0) =>
k < 0
? 0
: converge (k - 1) + (Math.pow (-3, -k)/(2 * k + 1))
console.log (converge (1000)) // 0.9068996821171091
console.log (Math.PI/Math.sqrt (12)) // 0.9068996821171089
,它可以帮助可读性,如果你抽象sigma
第一
const sigma = f => k =>
k < 0
? 0
: f (k) + sigma (f) (k - 1)
// hey, this looks just like the formula you posted
const converge =
sigma (k => Math.pow (-3, -k)/(2 * k + 1))
console.log (converge (1000)) // 0.9068996821171091
console.log (Math.PI/Math.sqrt (12)) // 0.9068996821171089
堆栈安全
我想指出的是,栈是从来没有超过四溢的危险 - 它会采取大约10,000 k
- 值产生溢出
console.log (converge (1e4)) // RangeError: Maximum call stack size exceeded
在这种情况下,这并不重要,因为即使是一个微小的k
- 10的值已经计算出小数点后六位;一个k
- 值100计算14位小数
但不管怎样,也许你有一些库,可以让计算更精确小数和你想converge
stack safe ...
const recur = (...args) =>
({ type: recur, args })
const loop = f =>
{
let acc = f()
while (acc && acc.type === recur)
acc = f (...acc.args)
return acc
}
// now stack-safe
const sigma = f => n =>
loop ((acc = 0, k = n) =>
k < 0
? acc
: recur (acc + f (k), k - 1))
const converge =
sigma (k => Math.pow (-3, -k)/(2 * k + 1))
console.log (converge (1e4)) // 0.9068996821171089 << super precise !!
console.log (Math.PI/Math.sqrt (12)) // 0.9068996821171089
答
永远不会在cnvg()
中分配,导致无限递归。您的意思是:
function cnvg(sum, marker) {
marker = (typeof(marker) === 'undefined') ? 1000 : marker;
if (marker-- >= 0) {
return cnvg(sum=(sum||0) + 1/Math.pow(-3,marker)/(2*marker+1), marker)
} else {
return sum;
}
}
但是这给了我3 + Math.PI/Math.sqrt(12)...(3.9068996821171087)
marker--
进行减法检查后,导致与marker = -1
附加的词。使用--marker
或> 0
,或更清楚:
marker = (typeof(marker) === 'undefined') ? 1000 : marker - 1;
if (marker >= 0) {
// ...
'marker - '在问题的代码中不会减少'marker'? – naomik
这是密切的...但这是给我'3 + Math.PI/Math.sqrt(12)'...(3.9068996821171087) –
谢谢亚伦,图片上传... –