我想找到正弦函数的零点。参数是区间[a,b]。我必须与二分搜索类似。
实现一个在a和b之间的间隔中搜索窦函数中的空点的函数。搜索间隔[下限,上限]应减半,直到下限和上限小于0.0001。
这是我的代码:
public class Aufg3 {
public static void main(String[] args) {
System.out.println(zeropoint(5,8));
}
private static double zeropoint(double a, double b){
double middle = (a + b)/2;
if(Math.sin(middle) < 0){
return zeropoint(a,middle);
}else if(Math.sin(middle) > 0){
return zeropoint(middle,b);
}else{
return middle;
}
}
}
它在返回zeropoint(中间,b)的行中给了我很多错误;
在第一步中,我想找到间隔中的第一个零点。
有什么想法吗?
答案 0 :(得分:6)
每个人都忽视的基本问题:
显然,需要的是一组(可能是空的)。
函数的伪代码确实要求(不使用Java,因为这是作业):
Set zeropoint(double a, double b)
{
double middle = mid point of a and b;
if a and be less than 0.0001 apart
{
if (sin(a) and sin(b) are on opposite sides of 0)
{
return set containing middle
}
else
{
return empty set
}
}
else
{
return union of zeropoint(a, middle) and zeropoint(middle, b)
}
}
答案 1 :(得分:3)
简单地说“它给我的错误”并不是很有帮助。什么样的错误?在运行时编译错误或未捕获的异常?
对于您的代码,有两个问题可能会出现问题:
mitte
似乎没有在任何地方声明。也可能存在其他问题,我只是写下乍看之下跳出来的那些。
编辑:
显然mitte
是由于OP通过粘贴代码时出错(并且已经被纠正)。正如其他答案所指出的那样,代码属于无限递归。这是因为递归调用的时间间隔错误。
有一点需要注意,对于a和b的一个选择,sin函数可以单调递增,而在某个其他区间单调递减。例如它增加超过[0,pi / 2]并且在[pi / 2,3 * pi / 2]上减小。因此,递归调用需要根据进行搜索的原始间隔而改变。对于一个间隔,Math.sin(中)<0意味着Math.sin(x)<0,对于[a,middle]中的所有x ],但对于其他一些区间则相反。这可能是为什么这会在您尝试的间隔内进入无限递归。我认为这适用于罪恶实际减少的其他一些区间。尝试通过[pi / 2,3 * pi / 2]调用你的函数。
答案 2 :(得分:3)
我猜你在运行时遇到堆栈溢出错误。 &lt;和&gt;迹象是逆转的。此外,您应该使用.0001而不是0来比较。
编辑1: 实际上,您的基本算法存在问题。如果间隔中有多个零,会发生什么?如果罪(a)和罪(mitte)有相同的符号会发生什么?如果区间内没有零会怎么样?
编辑2: 好的,所以我解决了问题,从根本上说,你的解决方案存在问题;我会尝试重新思考如何解决它。
主要问题是区间内可能存在多个零,并且您正试图找到它们中的每一个。创建返回double类型的函数只能返回一个解决方案。因此,不要创建一个返回double的函数,只需返回void并在找到它时打印出零。
另一个暗示:你应该继续搜索,直到a和b在彼此的0.0001之内。您的最终解决方案不会以任何其他方式使用.0001。 (即,检查你是否找到零不应该使用.0001容差,也不会使用0。请考虑当abs(ab)小于.0001时你是否真的知道你是否真的知道零
答案 3 :(得分:2)
你到底读完作业了吗?它说:
搜索间隔[下限,上限 应该减半,直到更低 限制和上限小于那个 相距0.0001。
因为浮点精度问题,所以你不能指望Math.sin(middle)
正好返回零。相反,当你达到0.0001精度时,你需要停止递归。
答案 4 :(得分:2)
我的猜测是你遇到了StackOverflowError
。这是因为您在递归时从未达到基本情况。 (Math.sin(middle)
可能永远不会等于完全 0!)
你的运动说
[...]直到下限和上限相距0.0001以下。
所以,试着把它放在你的方法之上:
double middle = (a + b)/2;
if (b - a < 0.0001)
return middle;
答案 5 :(得分:1)
除了其他人提到的一些浮点问题,你的算法似乎是基于隐含的假设:
我认为这些假设没有根据。如果其中任何一个是假的,我不希望你的算法工作。当a = 5且b = 8时,它们都是假的。
答案 6 :(得分:0)
if(Math.sin(mitte) < 0){
mitte
在哪里宣布?不是mitte
middle
?
答案 7 :(得分:0)
private static double zeropoint(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 (Math.abs(sin) < 0.0001) {
result = middle;
} else if (sin > 0) {
result = zeropoint(a, middle);
} else {
result = zeropoint(middle, b);
}
}
return result;
}
我认为这样的事情 - 只是为了修复第一个错误