我发现,做到这一点的一种方法是不时地“稍后再做”:
function knowNFactorial(n) {
return new Promise(function(resolve,reject) {
n = BigInt(n);
if (n === 1n) {
resolve(1n);
} else {
if (n % 1000n !== 0n) {
knowNFactorial(n - 1n).then(v => resolve(n * v));
} else {
// just "do it later" once in a while
setTimeout(() => {
knowNFactorial(n - 1n).then(v => resolve(n * v));
},0)
}
}
});
}
knowNFactorial(20000).then(v => console.log("I know its binary representation length is",v.toString(2).length));
// Only do the following inside of Node or Google Chrome developer console:
// knowNFactorial(20000).then(v => console.log("I know it is",v));
但是关于此还有其他通用技术或研究吗?当然,我们不必使用递归来解决factorial(n)
,但是如果存在需要递归的问题,并且如果可能发生堆栈溢出,则似乎存在一种技术:在任何可能的堆栈溢出之前,只需再创造一个承诺(并退出递归)。
仅在Node或Google Chrome内部打印出整个结果。如果在代码段内完成操作,则效果可能会不太理想。 (可能body
包含大数字而没有自动换行的方式太宽了,并且占用了大量内存):
knowNFactorial(20000).then(v => console.log("I know it is",v));
否则,一种方法就是将其转换为二进制并打印结果的数字长度,如代码段所示。
如果它是factorial(n)
的常规递归,则通常在n
超过12,000
或{{1}以上时,它会在我的Node或Google Chrome上堆栈溢出}}。我刚刚尝试使用上面的代码,将20,000
设为n
,但这不是问题。