In the second solution, there is overflow, but it's predictable. The sum can only require one extra bit, and the specification says that the low-order bits will be correct and that the sign bit will be flipped. It's using the sign bit to store the overflow, essentially.

I think you're right that things wouldn't be so simple in the second two solutions if "low" and "high" were unsigned to begin with. In that case, I think it's not clear what the high bit should be after adding and shifting because you don't know whether there was overflow.

]]>The bug is in this line: 6: int mid =(low + high) / 2;… So what's the best way to fix the bug? Here's one way: 6: int mid = low + ((high - low) / 2);Probably faster, and arguably as clear is: 6: int mid = (low + high) >>> 1;In C and C++ (where you don't have the

`>>>`

operator), you can do this: 6: mid = ((unsigned) (low + high)) >> 1;

Both of the last two solutions still add "low" and "high" together, so they could still overflow. The last one assumes that casting them to unsigned is enough, and it is unless someone already made "low" and "high" unsigned for other reasons.

The middle one just seems to assume that right-shifting (low + high) to the right by one bit with zero fill works, but that's not immediately obvious to me. Hmm…I guess that as long as the overflow can't be more than one bit, and adding two values together it can't be more than one bit, then right-shifting while clearing the high bit is exactly the right thing to do. It's just clearing the sign bit on the result, basically.

But that presumes that (low + high) does the right bitwise arithmetic and doesn't do any fancy formatting. That is, in 16-bit land, that adding 65535 and 65535 gives 0xFFFE with an overflow bit. If that's not *defined*, then the last solution won't work in all cases either. If it is defined to behave that way, it seems rather clever.

]]>