Почему мы пишем lo + (hi-lo)/2 в бинарном поиске?

Я читал о бинарном поиске... Я знаю, что традиционный способ нахождения среднего значения похож на

mid=(hi+lo)/2

Но я также вижу, что во избежание переполнения среднее значение вычисляется так, как

mid=lo+(hi-lo)/2

Но почему? Я не мог найти настоящую причину. Может ли кто-нибудь объяснить мне причину с примером? Это отличается от другого вопроса, потому что у других вопросов не было ответа, который я хотел с примером...

Ответ 1

Предположим, что вы ищете массив из 4000000000 элементов, используя 32-разрядные unsigned int в качестве индексов.

Первый шаг заставил его выглядеть так, как будто искомый элемент, если он присутствует, будет в верхней половине. lo значение 2000000000 и hi равно 4000000000.

hi + lo переполняет и производит значение, меньшее, чем предполагаемое 6000000000. Он фактически производит 6000000000-2 32. В результате (hi + lo) / 2 является небольшим значением. Это даже не между lo и hi!

С этого момента поиск будет неправильным (вероятно, он заключит, что элемент отсутствует, даже если он был там).

В отличие от этого, даже с экстремальными значениями в этом примере, lo + (hi - lo) / 2 всегда вычисляет индекс на полпути между hi и lo, как это предусмотрено алгоритмом.

Ответ 2

Математически говоря, они эквивалентны.

В терминах компьютера mid=(hi+lo)/2 выполняется меньше операций, но mid=lo+(hi-lo)/2 является предпочтительным, чтобы избежать переполнения.

Скажем, что элемент, который вы ищете, находится ближе к концу массива, тогда hi+lo почти 2*size. Поскольку size может быть почти таким же большим, как ваш максимальный индекс, 2*size и, следовательно, hi+lo может переполняться.