Question

I want to create a Java method which returns the lowest root of a quadratic equation in the interval (0, 1). If there are no solutions in the interval, return 1. I need some help making this an efficient algorithm.

This is my current method:

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;
}

This method does the job but I was wondering if there is a way to compress the algorithm, because right now it feels bloated.

Était-ce utile?

La solution

1) note that "less lines of code" isn't the same as "better performance".

2) you can consider Math.abs(sD) < Epsilon - if yes, then you don't have to calculate both roots. I'm guessing that this can improve speed in such cases.

3) I think you can improve checking which root is smaller:

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)

So you can avoid swapping the roots:

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

// always x1 <= x2

Again, I'm guessing that this improves performance, but I didn't measure it.

So, the final answer would look something like this:

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top