3

我运行了一个java程序并得到了一个stackoverflow error,这个错误是在digamma函数中引起的,代码是

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参数增加到20M,但错误仍然存​​在,所以我认为我必须将其重写为非递归,但我没有将递归函数重写为非递归函数的经验。

4

1 回答 1

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在开始下一次迭代之前从结果中减去。

于 2013-04-28T02:15:52.540 回答