我有以下挑战:
实现一个在a和b之间的间隔中搜索窦函数的零点的函数。搜索间隔[下限,上限]应减半,直到下限和上限小于0.0001。
找到一个条件来决定必须继续搜索的减半间隔。因此,在将间隔缩短为两个间隔后,我们必须选择一个继续我们的搜索。
我们假设a和b之间的间隔只有一个零点。
我正在努力解决第一点。我已经对该主题提出了一些问题,这些问题对我有很大帮助,但现在我需要在java中实现它,但它还没有用。
到目前为止,这是我的代码:
private static double nullstelle(double a, double b){
double middle = (a + b)/2;
double result = middle;
if(Math.abs(a-b) > 0.0001){
double sin = Math.sin(middle);
if(sin > 0){
result = nullstelle(a, middle);
}else{
result = nullstelle(middle, b);
}
}
return result;
}
我尝试使用递归实现,但也许另一种方式会更好,我不知道。 有什么想法吗?
答案 0 :(得分:2)
由于在我们考虑的时间间隔内最多有一个过零点,因此有三种可能性:
如果二分点是零点,那么就完成了。
否则,包含零交叉的段必须在其端点上具有不同的符号。
递归在其端点上具有不同符号的段
答案 1 :(得分:2)
如果a和b之间只有一个零点,则表示符号(sin(a))!=符号(sin(b))。在用你的中点替换a或b时,你需要通过这样的方式确保这种情况仍然存在:
if (sign(sin(a)) == sign(sin(middle)))
result = nullstelle(middle, b);
else
result = nullstelle(a, middle);
将sign(x)定义为
int sign(double x) { return x >= 0 ? 1 : -1; }
答案 2 :(得分:1)
你差不多了。您可以根据符号更改选择间隔 - 如果符号在间隔的左右边界之间发生变化,则选择该间隔:
private static double nullstelle(double a, double b){
double middle = (a + b)/2;
double result = middle;
if(Math.abs(a-b) > 0.0001){
double sin = Math.sin(middle);
if(sin == 0) { // Rare case but might happen
result = middle;
} else if (Math.signum(sin) != Math.signum(b)) { // The sign changes between middle and b
result = nullstelle(middle, b);
} else if (Math.signum(sin) != Math.signum(a)) { // The sign changes between a and middle
result = nullstelle(a, middle);
} else {
// Throw an exception here, the sin function does not cross x axis in the given interval
}
}
return result;
}
另请注意,在给定间隔内,函数可能会越过x轴多次。然后,signum可能会在两个时间间隔内发生变化,此函数将只选择正确的一个(中间到b),您将失去一些解决方案。
答案 3 :(得分:1)
在[a,b]丰富的区间(a&lt; = x&lt; = b)中给出x,我们可以说应用程序f:[a,b] - &gt; R在[a,b]上有一个根,即那里当且仅当f(a)* f(b)<0时,有界区间[a,b]中的x是满足f(x)= o的x。
简单来说,区间上有一个根是该区间上函数变化的符号。
为了找到这一点,我们将使用间隔的二进制分区。
我会修改此代码,如下所示:
private static double nullstelle(double a, double b){
double middle = (a + b)/2;
if(Math.abs(a-b) < 0.0001){
return middle;
}
if(Math.sin(a)*Math.sin(middle)<0) {
return nullstelle(a, middle);
}
if(Math.sin(middle)*Math.sin(b)<0) {
return nullstelle(middle, b);
}
}