我想创建一个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;
}
这种方法完成了这项工作,但我想知道是否有办法压缩算法,因为现在它感觉很臃肿。
答案 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;
}