In breve, (high + low) >>> 1
è un trucco che utilizza il segno-bit non utilizzati per eseguire una corretta media di numeri non negativi.
Partendo dal presupposto che high
e low
sono entrambi non negativo, sappiamo per certo che la parte superiore del bit più (il segno-bit) è pari a zero.
Quindi sia high
sia low
sono in realtà numeri interi a 31 bit.
high = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
low = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
Quando li si sommano possono "rovesciarsi" nel bit superiore.
high + low = 1000 0000 0000 0000 0000 0000 0000 0000
= 2147483648 as unsigned 32-bit integer
= -2147483648 as signed 32-bit integer
(high + low)/2 = 1100 0000 0000 0000 0000 0000 0000 0000 = -1073741824
(high + low) >>> 1 = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
Come un intero a 32 bit con segno, è troppo pieno e ribalta negativo. Pertanto (high + low)/2
è errato perché high + low
potrebbe essere negativo.
Come interi a 32 bit senza segno, la somma è corretta. Tutto ciò che serve è quello di dividerlo per 2.
Naturalmente Java non supporta interi senza segno, quindi la cosa migliore che dobbiamo dividere per 2 (come intero senza segno) è la logica destra-shift >>>
.
Nelle lingue con interi senza segno (come C e C++), diventa più complicato dal momento che l'input può essere pieno di interi a 32 bit. Una soluzione è: low + ((high - low)/2)
fine di enumerare le differenze tra >>>
, >>
e /
:
>>>
è logico shift destro. Riempie i bit superiori con zero.
>>
è aritmetico a destra. Riempie la parte superiore con copie del primo bit originale.
/
è divisione.
Matematicamente:
x >>> 1
tratta x
come intero senza segno e lo divide per due. Arrotonda.
x >> 1
tratta x
come numero intero con segno e lo divide per due. Arrotonda all'infinito negativo.
x/2
tratta x
come numero intero con segno e lo divide per due. Arrotonda verso lo zero.
Presumo che tu ti stia riferendo a [il bug di ricerca binaria] (http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html) ? – Mehrdad
Come sai che risolve il problema di overflow? Inoltre, quale problema di overflow? –
Joshua Bloch mi ha detto: http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html – JohnPristine