我运行了一个java程序并获得stackoverflow error
,这个错误是由digamma function引起的,代码是
public static double digamma(double x) {
if (x >= 0 && x < GAMMA_MINX) {
x = GAMMA_MINX;
}
if (x < DIGAMMA_MINNEGX) {
return digamma(DIGAMMA_MINNEGX + GAMMA_MINX);
}
if (x > 0 && x <= S_LIMIT) {
return -GAMMA - 1 / x;
}
if (x >= C_LIMIT) {
double inv = 1 / (x * x);
return Math.log(x) - 0.5 / x - inv
* ((1.0 / 12) + inv * (1.0 / 120 - inv / 252));
}
return digamma(x + 1) - 1 / x;
}
常量定义如下(省略private static final
以供空间考虑)
double GAMMA = 0.577215664901532860606512090082;
double GAMMA_MINX = 1.e-12;
double DIGAMMA_MINNEGX = -1250;
double C_LIMIT = 49;
double S_LIMIT = 1e-5;
由于stackoverflow error
是由递归级别太深导致超出线程的堆栈大小(对吗?)所以我将Xss
参数增加到{{1}但是错误仍然存在,所以我认为我必须将其重写为非递归,但我没有将递归函数重写为非递归的经验。
答案 0 :(得分:1)
未经测试,但现在是:
public static double digamma(double x) {
double value = 0;
while (true){
if (x >= 0 && x < GAMMA_MINX) {
x = GAMMA_MINX;
}
if (x < DIGAMMA_MINNEGX) {
x = DIGAMMA_MINNEGX + GAMMA_MINX;
continue;
}
if (x > 0 && x <= S_LIMIT) {
return value + -GAMMA - 1 / x;
}
if (x >= C_LIMIT) {
double inv = 1 / (x * x);
return value + Math.log(x) - 0.5 / x - inv
* ((1.0 / 12) + inv * (1.0 / 120 - inv / 252));
}
value -= 1 / x;
x = x + 1;
}
}
由于代码几乎是尾递归的,所以诀窍是在整个身体上抛出一个循环。
捕获量是你最后的- 1 / x
。但由于它是附加的,你可以在开始下一次迭代之前从结果中减去1 / x
。