Я ищу эффективную формулу, работающую на Java, которая вычисляет следующее выражение:
(low + high) / 2
, которое используется для двоичного поиска.До сих пор я использовал «низкий + (высокий - низкий) / 2» и «высокий - (высокий - низкий) / 2», чтобы избежать переполнения и потери в некоторых случаях, но не обоих.Теперь я ищу эффективный способ сделать это, который был бы для любого целого числа (предполагая, что целые числа варьируются от -MAX_INT - 1 до MAX_INT).
ОБНОВЛЕНИЕ : Объединение ответов от Джандераи Питер Г. и экспериментируя некоторое время, я получил следующие формулы для элемента среднего значения и его непосредственных соседей:
Самая низкая средняя точка (равна floor((low + high)/2)
, например, [2 3] -> 2, [2 4] -> 3, [-3 -2] -> -3)
mid = (low & high) + ((low ^ high) >> 1);
Наивысшая средняя точка (равна ceil((low + high)/2)
, например, [2 3] -> 3, [2 4] ->3, [-3 -2] -> -2)
low++;
mid = (low & high) + ((low ^ high) >> 1);
До средней точки (равно floor((low + high - 1)/2))
, например, [2 3] -> 2, [2 4] -> 2, [-7 -3] -> -6)
high--;
mid = (low & high) + ((low ^ high) >> 1);
После средней точки (равной ceil((low + high + 1)/2))
, например, [2 3] -> 3, [2 4] -> 4, [-7 -3] -> -4)
mid = (low & high) + ((low ^ high) >> 1) + 1;
Или, без побитового и (&) и или (|), немного более медленный код (x >> 1
может быть заменен на floor(x / 2)
для получения формул без побитового оператора):
крайняя левая середина
halfLow = (low >> 1), halfHigh = (high >> 1);
mid = halfLow + halfHigh + ((low-2*halfLow + high-2*halfHigh) >> 1);
крайняя правая середина
low++
halfLow = (low >> 1), halfHigh = (high >> 1);
mid = halfLow + halfHigh + ((low-2*halfLow + high-2*halfHigh) >> 1);
перед средней точкой
high--;
halfLow = (low >> 1), halfHigh = (high >> 1);
mid = halfLow + halfHigh + ((low-2*halfLow + high-2*halfHigh) >> 1);
после средней точки
halfLow = (low >> 1), halfHigh = (high >> 1);
mid = halfLow + halfHigh + ((low-2*halfLow + high-2*halfHigh) >> 1) + 1;
Примечание : указанный выше оператор >>
считается смещением со знаком.