For example, part of the code of an article I wrote before https://blog.csdn.net/qq_34115899/article/details/79526538
public int rank(int key, int n) { int lo = 0, hi = n - 1; while (lo <= hi) { int mid = lo + ((hi - lo) >> 1); //>>1 is divided by 2 or directly (lo + hi) >>> 1 // Why not directly (lo+hi)>>1, because lo+hi may overflow, but hi-lo does not overflow, lo+(hi-lo)>>1 is less than hi, and it does not overflow, which is safer int cmp = key - a[mid];// a is an ordered array if (cmp < 0) { hi = mid - 1; } else if (cmp > 0) { lo = mid + 1; } else { return mid; } } return lo; }
I use the mid processing method above
int mid = lo + ((hi - lo) >> 1);
But I found that Arrays.binarySearch() method when dealing with mid
int mid = (low + high) >>> 1;
Bitwise operators in Java:
>> means arithmetic right shift, if the number is positive, the high order is filled with 0, if it is negative, the high order is filled with 1;
>>> means logical right shift , also known as unsigned right shift , that is, if the number is positive, the high-order bits are filled with 0, and if the number is negative, the high-order bits are also filled with 0 after the right shift.
For example, int range -2147483648~2147483647
It is more than 2.1 billion. If the input exceeds the int range, the compiler will report an error, and obviously you will know that you are wrong. But the key is that each number entered is large and does not exceed the int range, but the addition or multiplication operation is out of range! ! ! This situation is difficult to detect and will cause unnecessary trouble
>>>1 operation is very good, for example
Do the following respectively:
System.out.println(1500000000 + 1500000000);
System.out.println((1500000000 + 1500000000) >> 1);
System.out.println((1500000000 + 1500000000) >>> 1);
show
-1294967296 (150000000 + 1500000000 (1.5 billion plus 1.5 billion))
10110010110100000101111000000000
-647483648 (>>1 case)11011001011010000010111100000000
1500000000 (>>>1 case)01011001011010000010111100000000 (just add and divide by 2, that is, unsigned right shift one bit)
Another set of examples
Do the following respectively
System.out.println(1500000000 + 1200000000); // 15亿加12亿
System.out.println((1500000000 + 1200000000) >> 1);
System.out.println((1500000000 + 1200000000) >>> 1);
show
-1594967296
10100000111011101011101100000000
-797483648 (after >>1)11010000011101110101110110000000
1350000000 (after >>>1)01010000011101110101110110000000 (just add and divide by 2, that is, unsigned right shift one bit)
To sum up, >>>1 is safer and will not affect the result due to overflow from addition .
But >>>1 can only solve the problem of addition overflow , and almost cannot solve the problem of multiplication overflow (unless there is a coincidence like multiplying by 2 and then >>>1, the high-order data is truncated and not saved), the solution is Use a larger data type to handle multiplication overflow.
============================== I am a slow programmer ============= =============