В (high + low) >>> 1
все еще может быть подписанный перенос, но оператор >>>
обрабатывает свой левый операнд как без знака , поэтому подписанный перенос не имеет значения.Этот подход работает, потому что unsigned wraparound: high
и low
не являются (как целые числа со знаком) неотрицательными, так что как целые числа без знака они не могут быть достаточно большими, чтобы вызвать обход без знака.
То, что добавление двух неотрицательных целых чисел со знаком никогда не страдает от обхода без знака, можно увидеть, сложив максимально возможные числа: 2 k-1 -1 + 2 k-1 -1 (где k - размер в битах целочисленного типа, обычно 32), что в сумме составляет 2 k -2.Это еще не все: наибольшее представимое число - 2 k -1.
Так что не «переполнение» в high + low
действительно вызывает проблему, по крайней мере, вразумный язык, где безопасна арифметика со знаком, такая как Java.Последующая обработка результата high + low
как целого числа со знаком гипотетической / 2
, которая следует за ним, вызывает проблемы.