0

我想创建一个 Java 方法,它返回区间中二次方程的最低根(0, 1)。如果区间内没有解,则返回1。我需要一些帮助,使它成为一种有效的算法。

这是我目前的方法:

public static float getLowestRoot(float A, float B, float C) {
    float D = B*B - 4*A*C;
    if(D < 0) return 1;

    float sD = (float) Math.sqrt(D);

    float x1 = (-B + sD) / (2*A);
    float x2 = (-B - sD) / (2*A);

    if(x2 < x1) {
        float tmp = x2;
        x2 = x1;
        x1 = tmp;
    }

    if(x1 > 0 && x1 < 1) return x1;
    if(x2 > 0 && x2 < 1) return x2;

    return 1;
}

这种方法可以完成工作,但我想知道是否有压缩算法的方法,因为现在感觉很臃肿。

4

1 回答 1

0

1)请注意,“更少的代码行”与“更好的性能”不同。

2)您可以考虑Math.abs(sD) < Epsilon- 如果是,那么您不必计算两个根。我这可以在这种情况下提高速度。

3)我认为你可以改进检查哪个根更小:

x1 <= x2 <===>  -B+sD/(2A) <= -B-sD/(2A) <==(adding sD/(2A) to both sides)==> 
         <===> -B+2sD/(2A) <= -B/(2A)    <==(adding B/(2A) to both sides)==>
         <===>    2sD/(2A) <= 0
         <===>           A <= 0 (because sD >= 0)

所以你可以避免交换根:

int signA = Math.signum(A);
float x1 = (-B + -signA * sD) / (2*A);
float x2 = (-B + signA * sD) / (2*A);

// always x1 <= x2

同样,我猜测这会提高性能,但我没有测量它。

所以,最终的答案看起来像这样:

public static float getLowestRoot(float A, float B, float C) {
    float D = B*B - 4*A*C;

    if (D < 0) return 1;

    if (Math.abs(D) < 0.0001)  // not sure how many 0s for float
    {
        float x = -B / (2*A);

        if (x > 0 && x < 1) return x;

        return 1;
    }

    float sD = (float) Math.sqrt(D);

    int signA = Math.signum(A);
    float x1 = (-B + -signA * sD) / (2*A);
    float x2 = (-B + signA * sD) / (2*A);

    if (x1 > 0 && x1 < 1) return x1;
    if (x2 > 0 && x2 < 1) return x2;

    return 1;
}
于 2013-10-15T13:37:24.203 回答