News for hackers. Stuff that matters.
Re:Binary search with confidence by orlp on Monday March 07, 2022 @07:16AM (#30586851)
I am a huge proponent of "bitwise" binary search. Consider r to be the result index we wish to find in range [0, n), that is, the first index where a predicate returns false, or n if there is no such predicate. We can construct this index bit-by-bit, starting from the most significant bit:

    # Extracts the highest set bit for n > 0.
    # This can be 1-5 instructions on most machines using count leading zeros.
    def highest_bit_set(n):
        return 1 << (n.bit_length() - 1)

    def binary_search(n, predicate):
        # Construct largest possible r such that predicate(r) is true, or 0.
        if n == 0: return 0
        r = 0
        bit = highest_bit_set(n)
        while bit:
            if (r | bit) < n and predicate(r | bit): r |= bit
            bit >>= 1

        # Return smallest possible r such that predicate(r) is false, or n.
        if r > 0 or predicate(0): r += 1
        return r
I find this to be significantly easier to reason about, although I do have a lot of experience with bitwise manipulation. And it is trivial to extend to search a range [lo, hi):

    def binary_search_range(lo, hi, predicate):
        return binary_search(hi - lo, lambda i: predicate(lo + i))
It's similarly trivial to reason they do exactly log2(n) or log2(hi - lo) iterations and are thus worst-case optimal.
Re:Binary search with confidence by truly on Monday March 07, 2022 @08:29AM (#30587471)
This is called bisection search (search for the largest/smallest value satisfying a given predicate).

It also reminds me a little bit of exponential search (upper bound unknown), although obviously the upper bound is known in your implementation.

Bisection: https://en.wikipedia.org/wiki/Bisection_method Exponential search: https://en.wikipedia.org/wiki/Exponential_search

A practical application of bisection search is in git bisect (https://git-scm.com/docs/git-bisect) to find the first revision that introduced a bug.

Re:Binary search with confidence by hddqsb on Monday March 07, 2022 @11:44AM (#30590027)
Note that with this version, the expected number of calls to `predicate` can be 1 more than strictly necessary (depending on n). This happens when n is one more than a power of 2, e.g. if n is 65 then `bit` is 64 and the first call will be `predicate(64)`, which is basically useless in reducing the search space.
Re:Binary search with confidence by orlp on Monday March 07, 2022 @02:40PM (#30592393)
This is true, if your comparison operator is very expensive you should (very, very carefully) implement the traditional binary search.