为什么二进制搜索的中点算法使用
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="recurrent">
<label for="recurrent">Recurrent?</label>
<input type="radio" id="idtrue" name="recurrent" value="true">Yes
<input type="radio" id="idfalse" name="recurrent" value="false" checked>No
</div>
<div id="ifRecurrentTrue">
/// something
</div>
而不是
low + (high-low)/2
答案 0 :(得分:3)
你的问题被标记为python,所以我将回答python。简而言之,它没有:
https://hg.python.org/cpython/file/2.7/Lib/bisect.py
found in the docs以上的pythonic实现使用后者的构造。正如评论中的人们指出的那样,some languages need to respect overflow。 Python isn't none of them并且具有任意精度整数。
在评论中推测,从类C语言移植的人可能会复制该语言更可接受的结构。这个有可能。其他人评论说,一个可能比另一个更快;一般来说,这样的微观优化似乎很难评论。
但是......如果他们不是,那该怎么办?
我假设这些是整数,因为对于二进制搜索,索引是整数。如果它们确实不是整数,那么使用它们访问数组会遇到一些问题。但与此同时,您可能会遇到不同的结果:
a = b = sys.float_info.max
print a + (a-b)/2 # prints a really big number
print (a+b)/2 # prints inf
类似地,
a = b = float("inf")
print a+(a-b)/2 # prints nan
print (a+b)/2 # prints inf
后一个例子不同,虽然我不清楚哪个更好。为什么会发生这种情况,您可以查看上面链接的文章中的溢出说明。
答案 1 :(得分:0)
我在google上搜索了这个问题,并在http://googleresearch.blogspot.in/2006/06/extra-extra-read-all-about-it-nearly.html
上找到了非常有趣的答案以下是示例:
1: public static int binarySearch(int[] a, int key) {
2: int low = 0;
3: int high = a.length - 1;
4:
5: while (low <= high) {
6: int mid = (low + high) / 2;
7: int midVal = a[mid];
8:
9: if (midVal < key)
10: low = mid + 1
11: else if (midVal > key)
12: high = mid - 1;
13: else
14: return mid; // key found
15: }
16: return -(low + 1); // key not found.
17: }
错误就在这一行:
int mid =(low + high) / 2;
在编程中Pearls Bentley说类似的行“将m设置为l和u的平均值,截断为最接近的整数”。从表面上看,这个断言可能看起来是正确的,但是对于低变量和高变量的int变量的大值,它都失败了。具体地说,如果low和high的总和大于最大正int值(231-1),则失败。总和溢出为负值,当除以2时,该值保持为负。在C中,这会导致数组索引超出范围,结果不可预测。在Java中,它会抛出ArrayIndexOutOfBoundsException。
对于长度(元素中)为230或更大(大约十亿个元素)的数组,此错误可以表现出来。这在80年代编程珍珠编写时是不可想象的,但现在谷歌和其他地方很常见。在编程珍珠中,Bentley说:“虽然第一次二元搜索是在1946年发布的,但是第一次正确处理所有n值的二元搜索直到1962年才出现。”事实上,至少在主流编程语言中,很少有正确的版本发布过。
那么修复bug的最佳方法是什么?这是一种方式:
int mid = low + ((high - low) / 2);