what's the difference between mid=(beg+end)/2 and mid=beg+(end-beg)/2 in binary search?

空扰寡人 提交于 2019-12-22 04:07:41

问题


It is a problem from C++ primer fifth edition problem 3.26, I don't know the difference between them ? May be the second one can avoid overflow.


回答1:


May be the second one can avoid overflow.

Exactly. There's no guarantee that beg+end is representable; but in the second case the intermediate values, as well as the expected result, are no larger than end, so there is no danger of overflow.

The second form can also be used for affine types like pointers and other random-access iterators, which can be subtracted to give a distance, but not added together.




回答2:


In general case the both expressions are invalid. For example the first expression is invalid because there is no such operation as + for pointers or iterators. The second expression is invalid in case when non-random access iterators are used. For example when bidirectional iterators are used.

So the correct construction in C++ will look the following way

mid = std::next( beg, std::distance( beg, end ) / 2 );



回答3:


If we consider the two lines in a more generic setting, not related to binary search, the following observations can be made:

You are correct that the problem the second form tries to avoid is overflow, attempting to represent a number that is larger than the maximum representable number.

There is no restriction on how large the individual numbers beg and end are, so potentially they can both be larger than half of the maximum representable number. Adding them means that the intermediate result (beg+end) can overflow.

The second solution seems to eliminate the risk of overflowing, but introduces another one. If the values are signed values, their difference can again overflow (or underflow, depending on their signs). Unsigned values have no problem.

There is another solution which you didn't post:

mid = beg/2 + end/2

This solves every problem with overflow and underflow, but introduces a new problem, of precision loss. If working with integer values, division by 2 can give a result off by 0.5, adding these together, means that mid can be off by 1:

mid = 3/2 + 5/2; // mid is 3, instead of the 4 expected

Working with floating point values has other precision problems.

Getting back to the problem at hand, the binary search, it's easy to see that beg and end are unsigned values, so the second solution will always give the correct result.




回答4:


The answer is in the book:

"Because the iterator returned from end does not denote an element, it may not be incremented or dereferenced."

Graphically it makes sense as an asymmetric range, [begin, off-the-end) or half-open range.

From Accelerated C++, page 28, Koenig.



来源:https://stackoverflow.com/questions/20998982/whats-the-difference-between-mid-begend-2-and-mid-begend-beg-2-in-binary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!