解释这些中点算法之间的区别

时间:2016-03-01 03:55:15

标签: python

为什么二进制搜索的中点算法使用

<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

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 overflowPython 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);