Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why M = L + ((R - L) / 2) instead of M=(L+R)/2 avoid overflow in C++?

Tags:

c++

Hello I was looking at the C++ solution to the question "Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). How do you find an element in the rotated array efficiently? You may assume no duplicate exists in the array."

int rotated_binary_search(int A[], int N, int key) {
    int L = 0;
    int R = N - 1;

    while (L <= R) {
    // Avoid overflow, same as M=(L+R)/2
        int M = L + ((R - L) / 2);
        if (A[M] == key) return M;

    // the bottom half is sorted
        if (A[L] <= A[M]) {
            if (A[L] <= key && key < A[M])
                R = M - 1;
            else
                L = M + 1;
        }
    // the upper half is sorted
        else {
            if (A[M] < key && key <= A[R])
                L = M + 1;
            else 
                R = M - 1;
        }
    }
    return -1;
}

and saw the comment says that using M = L + ((R - L) / 2) instead of M=(L+R)/2 avoid overflow. Why is that? Thx ahead

like image 893
user3692521 Avatar asked Aug 04 '14 07:08

user3692521


People also ask

How can we prevent integer overflow in binary search?

Unless you are using a language that does not overflow such as Python, l+r could overflow. One way to fix this is to use m=l+(r-l)/2 ​ instead so that the program will not fall under overflow bug.

Why is a binary search high low?

The value of low cannot be greater than high; this means that the key is not in the vector. So, the algorithm repeats until either the key is found or until low > high, which means that the key is not there. The following function implements this binary search algorithm.


3 Answers

Because it does...

Let's assume for a minute you're using unsigned chars (same applies to larger integers of course).

If L is 100 and R is 200, the first version is:

M = (100 + 200) / 2 = 300 / 2 = 22

100+200 overflows (because the largest unsigned char is 255), and you get 100+200=44 (unsigned no. addition).

The second, on the other hand:

M = 100 + (200-100) / 2 = 100 + 100 / 2 = 150

No overflow.

As @user2357112 pointed out in a comment, there are no free lunches. If L is negative, the second version might not work while the first will.

like image 159
zmbq Avatar answered Nov 15 '22 17:11

zmbq


Not sure, but if the max limit of int is suppose 100.

R=80 & L = 40
then, 
M=(L+R)/2
M=(120)/2, here 120 is out limits if our integer type, so this causes overflow

However,

M = L + ((R - L) / 2)  
M = 80 +((40)/2)
M = 80 +20
M =100.

So in this case we never encounter a value that exceeds the limits of our integer type.So this approach will never encounter a overFlow, THEORATICALLY.

I hope this analogy will help

like image 21
Parth Kapoor Avatar answered Nov 15 '22 18:11

Parth Kapoor


It avoids overflow in this specific implementation, which operates under the guarantees that L and R are non-negative and L <= R. Under these guarantees it should be obvious that R - L does not overflow and L + ((R - L) / 2) does not overflow either.

In general case (i.e. for arbitrary values of L and R) R - L is as prone to overflow as L + R, meaning that this trick does not achieve anything.

like image 39
AnT Avatar answered Nov 15 '22 18:11

AnT