找到特定间隔中的最低二次根

时间:2013-10-15 13:09:54

标签: java algorithm quadratic

我想创建一个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;
}

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

1 个答案:

答案 0 :(得分: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;
}