要するに、(high + low) >>> 1
未使用の符号ビットを使用して、負でない数値の正しい平均を実行するトリックです。
high
とlow
が両方とも非負であるという仮定の下で、最上位ビット (符号ビット) がゼロであることは確実です。
したがって、high
とlow
は実際には 31 ビット整数です。
high = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
low = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
それらを一緒に追加すると、トップビットに「こぼれる」場合があります。
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
もちろん、Java は符号なし整数をサポートしていないため、(符号なし整数として) 2 で除算する必要がある最善の方法は、論理右シフト>>>
です。
符号なし整数を使用する言語 (C や C++ など) では、入力が完全な 32 ビット整数になる可能性があるため、より複雑になります。1つの解決策は次のとおりです。low + ((high - low) / 2)
>>>
最後に、 、>>
、およびの違いを列挙します/
。
>>>
論理右シフトです。上位ビットをゼロで埋めます。
>>
算術右シフトです。元のトップビットのコピーでアッパーを埋めます。
/
分割です。
数学的に:
x >>> 1
x
符号なし整数として扱い、それを 2 で割ります。切り捨てます。
x >> 1
符号付き整数として扱いx
、それを 2 で除算します。負の無限大に向かって丸めます。
x / 2
符号付き整数として扱いx
、それを 2 で除算します。ゼロに向かって丸めます。