简体   繁体   中英

Binary searching to find an unknown number

I have a function called Slice. It consumes 2 values. First Node value and a second node value. I'm trying to find the value between [First,Second] inclusively that makes function G(x) go to zero or very near, closest by 2 decimal places. I can solve this problem using an iterative function starting at first number and incrementing by .01 but this could take a very long time.

I'm trying to have it with a binary run time. The tricky part is that I don't know which slice to take after I find the mid point. If I can get some tips or suggestions to continue please.

public double Slice(decimal first, decimal last)
{
    double firstNodeValue         = FinalOptionDecider(first);        

    double midNodeValue           = FinalOptionDecider((last + first) / 2);

    double lastNodeValue          = FinalOptionDecider(last);   
}

Binary search relies on sorted data to make the decision on which half to search next. So unless the function you want to pass your data through also retains your data in a sorted order, you cannot use binary search.

You have two options:

  • Give up on binary search and just do a linear search
  • Process all the inputs, sort and binary search the outputs (you can pair the input and output together in dictionary to retrieve the input).

As a general problem for an arbitrary function, this can be very difficult to solve. It becomes a lot easier if you can make certain assumptions. The algorithm you've sort of started to stub out is called a bisection algorithm.

First you need to bracket the value that you're looking for. So if you want FinalOptionDecider(x) to return zero, your firstNodeValue and lastNodeValue must be positive and negative. If they're both positive or both negative, you've failed to bracket the value that you want and you can't make any guarantee that searching between first and last will find an answer. And you also won't be able to guarantee that you can make the decision described in the next paragraph. So check for that first.

That condition is basically your answer... when you get the midNodeValue you need to check and see if your desired value is between firstNodeValue and midNodeValue or if it's between midNodeValue and lastNodeValue . Depending on which it is, you need to do a slice on that interval again. Repeat until you reach the desired precision.

If your function has multiple zeroes (like g(x) = x^2 - 1 does) then you will only find one of the zeroes.

The binary search is all about narrowing down an interval until the interval only consists of one value. I don't know what you mean by random but a binary sort can only be performed on a sorted dataset. Remember that it is almost always faster to search randomly than to sort and then search!

You're just looking for a root-finding algorithm . The one you've started implementing here is just the Bisection method . Bisection isn't the fastest, but it has the major advantage that it's simple and guaranteed to converge to a root in the specified interval provided the function changes sign over the interval and the function is continuous (thus, by the intermediate value theorem , a root is guaranteed to exist in the interval. Here's a simple, somewhat generic implementation of the bisection method:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM