我有一个名为Slice的函数。它消耗2个值。第一个节点值和第二个节点值。我试图找到[First,Second]之间的值,使函数G(x)变为零或非常接近,最接近2位小数。我可以使用从第一个数字开始并递增.01的迭代函数来解决这个问题,但这可能需要很长时间。
我正在尝试使用二进制运行时。棘手的部分是我发现中点后我不知道要采取哪个切片。如果我能得到一些提示或建议继续请。
public double Slice(decimal first, decimal last)
{
double firstNodeValue = FinalOptionDecider(first);
double midNodeValue = FinalOptionDecider((last + first) / 2);
double lastNodeValue = FinalOptionDecider(last);
}
答案 0 :(得分:1)
二进制搜索依赖于已排序的数据来决定下一个搜索的一半。因此,除非您想要传递数据的函数也按排序顺序保留数据,否则不能使用二进制搜索。
您有两种选择:
答案 1 :(得分:1)
作为任意函数的一般问题,这可能很难解决。如果你能做出某些假设,那就容易多了。您开始使用的算法称为二分算法。
首先,您需要包含您要查找的值。因此,如果您希望FinalOptionDecider(x)
返回零,则firstNodeValue
和lastNodeValue
必须为正数和负数。如果它们既是正面的,也可能都是负数,那么您无法将所需的值括起来,也无法保证在first
和last
之间进行搜索会找到答案。而且您也无法保证您可以做出下一段中描述的决定。所以先检查一下。
这个条件基本上就是你的答案......当你得到midNodeValue
时,你需要检查一下,看看你想要的值是否在firstNodeValue
和midNodeValue
之间,或者是否在{{1}之间1}}和midNodeValue
。根据它的不同,您需要再次对该间隔进行切片。重复,直到达到所需的精度。
如果你的函数有多个零(比如g(x)= x ^ 2 - 1那么),那么你只能找到一个零。
答案 2 :(得分:1)
二进制搜索是关于缩小间隔,直到间隔仅由一个值组成。我不知道你的意思是随机的,但二进制排序只能在排序的数据集上执行。 请记住,随机搜索几乎总是比排序然后搜索更快!
答案 3 :(得分:1)
您只是在寻找root-finding algorithm。您在此处开始实施的只是Bisection method。二分并不是最快的,但它的主要优点是它很简单并且保证在指定的时间间隔内收敛到 a 根,只要函数在区间内改变符号并且函数是连续的(因此,通过intermediate value theorem,一个根保证存在于区间中。这是一个简单的,有点通用的二分法方法实现:
public static decimal FindRoot( decimal first, decimal last, Func<decimal, double> f, double value, decimal tolerance = 0.01m )
{
double fa = f( first );
double fb = f( last );
if( fa * fb > 0 )
{
throw new ArgumentException( "Interval not guaranteed to contain root." );
}
else if( fa == 0 )
{
return first;
}
else if( fb == 0 )
{
return last;
}
while( Math.Abs( first - last ) > tolerance )
{
decimal mid = ( first + last ) / 2;
double fc = f( mid );
if( fc * fb < 0 )
{
first = mid;
fa = fc;
}
else if( fc * fa < 0 )
{
last = mid;
fb = fc;
}
else
{
return mid;
}
}
return ( first - last ) * (decimal) ( fa / ( fb - fa ) ) + first;
}