Here is the way to go. In Java:
mid = (high+low)/2 may give incorrect result. The maximum positive value (in Java) of int is, 2^(31)-1 or 2147483647 (in binary 0111 1111 1111 1111 1111 1111 1111 1111). The problem is that the intermediate value (high+low) could exceed this maximum int value. For example, if high and low, both are equal to 2^(31)-1, then the intermediate value becomes
high : 0111 1111 1111 1111 1111 1111 1111 1111
+low : 0111 1111 1111 1111 1111 1111 1111 1111
------------------------------------------------------
Intermediate : 1111 1111 1111 1111 1111 1111 1111 1110
And in 2's complement, this intermediate is
2's complement = 1's complement(Intermediate)+1, hence
(1's complement) 0000 0000 0000 0000 0000 0000 0000 0001
( +1) 1
--------------------------------------------------------
0000 0000 0000 0000 0000 0000 0000 0010
So, intermediate = -2. This -2 is like
[1111 1111 1111 1111 1111 1111 1111 11]10, where [...] is the sign extension.
Thus mid = -2/2 = -1, which is incorrect.
If we use mid = low+(high-low)/2, that overflow (intermediate exceeding maximum allowed value of
int) never happens, thus gives correct result.
Another incorrect way is mid = (high+low) >> 1; because the overflow has happened already before the shift and ">>" is the signed shift in Java, thus the intermediate
[1111 1111 1111 1111 1111 1111 1111 11]10 becomes
[1111 1111 1111 1111 1111 1111 1111 111]1, which is -1.
The best way is, mid = (high+low) >>> 1. Because ">>>" is the unsigned shift in Java, the intermediate
[1111 1111 1111 1111 1111 1111 1111 11]10 becomes
[0111 1111 1111 1111 1111 1111 1111 11]11 which is actually the correct mid (= 2^(31)-1).
No comments:
Post a Comment