の安全な平均の説明私は、バイナリサーチのようなアルゴリズムのための2つの数値を平均化する必要があるたびに、私はいつもこのような何か:二つの数
int mid = low + ((high - low)/2);
を私は最近this postでそれを行うための別の方法を見て、私はそれを理解していません。それはあなたがJavaでこれを行うことができます言う:
C++でint mid = (low + high) >>> 1;
またはこの:
int mid = ((unsigned int)low + (unsigned int)high)) >> 1;
C++バージョンは、本質的にその代わりに、署名の算術シフトでシフト結果をやって、両方のオペランドが符号なしになりますシフト。これらのコードの両方が何をしているのか理解していますが、どのようにオーバーフローの問題を解決しますか?全体の問題は、中間値high + low
がオーバーフローする可能性があると私は考えましたか?
編集:
ああ、当たり前。すべての答えが正確に私の質問に答えなかったが、それはそれをクリックした@ジョンZeringueの答えだった。私はここで説明しようとします。
Javaの(high + low)/2
の問題は、あくまでもhigh + low
のオーバーフローです(整数が両方とも署名されているのでオーバーフローしますが、すべてのビットはまだ存在し、情報は失われません)。このような平均をとる問題は部門です。部門は署名された値で動作しているため、結果はマイナスになります。代わりにシフトを使用すると、2で除算されますが、符号の代わりにビットを考慮します(事実上、符号なしとして扱います)。
Javaには符号なし整数がありません。あなたの 'int'がオーバーフローしたら何が起こるか考えてみてください。また、 ''>' 'が何をするかを考えてください。 –
私はあなたがそれを試し、それがどんな違いがあるのかを見ることをお勧めします。これは何十年もの間知られていた問題でしたので、あなたはそれを見ることができましたが、あなた自身でそれを理解することで詳細を知ることができます。 –