(高+低)/ 2の代わりに低+(高-低)/ 2を使用するのはなぜですか?目的はオーバーフローを防ぐことです!
なぜこれがオーバーフローを防ぐのですか?以下の例を見てください。
high = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
low = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
次に、これら2つの値を合計して、結果がどうなるかを確認します。
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
low + (high - low) / 2 = 0100 0000 0000 0000 0000 0000 0000 0000 = 1073741824
符号付き32ビット整数として、オーバーフローして負に反転します。したがって、操作の結果が現在のタイプで表される範囲を超える可能性があるため、これ(high + low) / 2
は誤りhigh + low
です。
符号なし32ビット整数として操作される場合、合計は正しいです。必要なのはそれを2で割るだけです。
符号なし整数はJava操作ではサポートされていないため、オーバーフローを防ぐために通常はlow +(high-low)/ 2を選択しますが、Javaではlow +(high-low)>>> 1と書く方法があります>違い>>と>>の間は、unsignedとsignedにあります。>>を使用すると、符号ビットも計算に参加します。
(high + low) >> 1 = 1100 0000 0000 0000 0000 0000 0000 0000 = -1073741824
一般的に、>>と>>>は/を除算するよりも効率的ですが、コンパイラーによる最適化の後、それらの効率はそれほど変わりません。作業で同僚と一貫性を保つようにしてください。許可なしにビット演算を使用しないでください。問題が発生する可能性があり、読み取りが困難になり、効率が大幅に向上することはありません。
記事の私の理解に逸脱や誤りがある場合は、コメントして読者を指摘してください、それは大歓迎です。