PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchBinary search finds a value—or a boundary—in a sequence sorted by the same ordering used for comparisons. Each midpoint comparison rules out part of the remaining candidates, so the search takes O(log n) comparisons in the worst case. The key to getting it right is to define the candidate interval and the result the routine promises before writing its loop.
Why binary search requires sorted data
Suppose the sequence is A and the target is x. At a midpoint m, if A[m] < x, sorted order proves that every element at or before m is also too small. If A[m] > x, every element at or after m is too large. Either comparison lets the search discard a region without inspecting it.
As an Amazon Associate I earn from qualifying purchases.
That deduction depends on the sequence being sorted under the same ordering used by the comparisons. In an unsorted sequence, a value smaller than x at the midpoint says nothing conclusive about values elsewhere; neither side can safely be discarded. Carnegie Mellon’s course notes on binary search describe the halving search and its logarithmic bound.
Define the candidate interval before updating it
A convenient convention is the half-open interval [L, R): L is included and R is excluded. The candidate indices are therefore L through R−1; when L = R, no candidates remain. For an array of length n, maintain 0 ≤ L ≤ R ≤ n.
#1 Best Overall
For exact-match search, the invariant is: if x occurs in the array, at least one occurrence is still in [L, R). Initially the interval is [0, n), so it contains every array index. While L < R, choose m = L + floor((R − L) / 2). This midpoint belongs to the active interval.
- If
A[m] = x, returnm; it is a matching index. - If
A[m] < x, setL = m + 1. Sorted order rules out every index throughm. - If
A[m] > x, setR = m. Sorted order rules outmand every later index.
Each update makes the interval smaller. If the loop ends at L = R without finding a match, no candidate remains, so the target is absent. This invariant explains both why the result is correct and why the algorithm terminates. The INRIA Toccata/Why3 verification example illustrates how a binary-search contract can state sortedness, the meaning of a returned index, and the absence condition.
Why the comparison count is logarithmic
After each unsuccessful comparison, the active interval is reduced to at most about half its previous size. Repeating that reduction takes roughly one comparison level per doubling of the input size: doubling the number of candidates adds about one level. The worst-case comparison count is therefore O(log n), as opposed to checking up to n entries one by one. This is a bound on comparisons for the halving search, not a hardware benchmark.
Choose the result contract: a match or a boundary
An exact-match routine may return any matching occurrence when duplicates exist. It does not promise the first occurrence unless its contract and updates specifically provide that guarantee. If callers need a predictable duplicate position—or an insertion point—use a boundary search instead.
Rank #3
Lower bound: first element not less than the target
A lower-bound search returns the first index i such that A[i] ≥ x. With duplicates, that is the first equal element. If every element is less than x, the result is n, the position after the last element. Maintain a half-open interval of possible boundary positions and use the predicate A[m] < x: when it is true, the boundary must be to the right of m, so set L = m + 1; otherwise retain m as a possible boundary by setting R = m. The same L < R loop ends with L = R, the lower-bound index.
Upper bound: first element greater than the target
An upper-bound search returns the first index i such that A[i] > x. Its predicate is A[m] ≤ x: if true, the boundary lies after m; otherwise it is at or before m. Use the corresponding updates L = m + 1 and R = m. The result can also be n if no element is greater than x. These two boundary contracts are useful for locating a duplicate range: lower bound gives its start, upper bound gives the position just after it.
Rank #4
- Grokking Algorithms: An illustrated guide
- For programmers and other curious people
- It is made up of premium quality material.
Prevent midpoint overflow
In fixed-width integer languages, (low + high) / 2 can overflow even when both indices are valid: their sum may exceed the largest representable signed integer. Joshua Bloch described this bug in a Java implementation and noted that the particular signed 32-bit expression can fail for arrays of at least 230 elements. That threshold applies to the implementation and integer width he discussed, not to every language or machine.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
For nonnegative indices where high ≥ low and subtraction is safe, low + ((high - low) / 2) avoids forming their sum. The half-open formula L + floor((R - L) / 2) follows the same idea. Safety still depends on the language’s integer rules and the valid range of indices; signed overflow in C or C++, for example, has language-specific consequences, so do not assume a shift or unsigned conversion is interchangeable across languages. Bloch’s 2006 explanation of the midpoint bug gives the Java example and its fix.
Best Value
Use the interval convention consistently
Half-open and inclusive intervals are both valid, but their loop conditions and updates are not interchangeable. The half-open form above searches [L, R), loops while L < R, and can represent the empty range with L = R. An inclusive form commonly searches [low, high] and loops while low ≤ high; its midpoint is still a candidate, and updates must exclude it without leaving it in the next interval. Mixing a half-open update with an inclusive loop, or vice versa, is a common source of off-by-one errors.
- Write down whether each endpoint is included.
- State the invariant in terms of the exact indices that remain possible.
- Make each branch remove the midpoint or a region that sorted order proves cannot contain the answer.
- Specify what happens when the target is absent and whether duplicates return any match or a defined boundary.
- Check empty and one-element inputs, plus targets below, within, and above the sequence.
Why a short search loop still needs a proof
Binary search is small enough to look obvious, but correctness depends on the details: the precondition, invariant, branch updates, arithmetic, and termination condition must agree. Carnegie Mellon’s January 30, 2014 lecture notes quote Jon Bentley’s report that “only about ten percent of professional programmers were able to get this small program right.” That is a reported classroom exercise, not a current population-wide measurement. The notes also quote Bentley’s point that loop invariants help programmers compose correct programs.
A historical observation quoted in those notes and in Bloch’s post says the first binary search was published in 1946, while the first one that worked correctly for all values of n did not appear until 1962. This is a secondary-source account attributed through Bentley and Knuth, rather than a claim verified here against the original publications.
Free tools Windows power users keep installed
One-click scans. No signup required.
For a deeper treatment of reasoning about small programs, Jon Bentley’s Programming Pearls, 2nd Edition, includes “The Challenge of Binary Search” in its chapter on writing correct programs, according to the publisher’s contents page.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




