【问题标题】:Why we write lo+(hi-lo)/2 in binary search? [duplicate]为什么我们在二分查找中写 lo+(hi-lo)/2? [复制]
【发布时间】:2014-10-23 15:32:19
【问题描述】:

我正在阅读二进制搜索...我知道查找中间值的传统方法就像

mid=(hi+lo)/2

但我也看到,为了避免溢出,中间值是这样计算的

mid=lo+(hi-lo)/2

但是为什么?我找不到真正的原因..有人可以举个例子吗? 它与其他问题不同,因为其他问题没有我想要的答案...

【问题讨论】:

  • 原因在你的问题中,避免溢出。
  • 这个问题是题外话,因为它是一个带问号的答案。
  • 我没有得到任何示例..我想要示例..
  • 假设 hi 和 lo 是指针(或 C++ 中的迭代器)。两个指针之和没有意义。两个指针的区别是,它是一个整数。向指针添加整数也很有意义。

标签: c++ algorithm binary-search


【解决方案1】:

假设您正在搜索一个使用 32 位 unsigned int 作为索引的 4000000000 元素数组。

第一步使它看起来好像搜索到的元素(如果存在)将在上半部分。 lo 的值为2000000000hi 的值为4000000000

hi + lo 溢出并产生一个小于预期6000000000 的值。它实际上产生 6000000000-232。因此,(hi + lo) / 2 是一个很小的值。甚至不在lohi 之间!

从那时起搜索将是错误的(它可能会得出该元素不存在的结论,即使它存在)。

相比之下,即使在此示例中使用极值,lo + (hi - lo) / 2 也始终按照算法的预期计算介于 hilo 之间的索引。

【讨论】:

  • @ikegami 因为我选择了unsigned int 类型,所以添加不是未定义的行为,它被简单地定义为产生环绕结果。
  • 有趣。谢谢。
  • 当 16 位架构统治地球时,这个问题更有可能再次出现。
  • @MarkRansom Google 工程师(重新)在 2006 年发现了 32 位:googleresearch.blogspot.fr/2006/06/…
【解决方案2】:

从数学上讲,它们是等价的。

在计算机方面,mid=(hi+lo)/2 操作较少,但首选mid=lo+(hi-lo)/2 以避免溢出。

假设您正在搜索的项目接近数组的末尾,那么hi+lo 几乎是2*size。由于size 几乎可以与您的最大索引一样大,因此2*sizehi+lo 可能会溢出。

【讨论】:

  • hi + lo 可以溢出。如果lo, hi 是范围内的正整数和lo <= hilo+(hi-lo)/2 将永远不会溢出。
  • 数值溢出与可寻址空间的大小无关,而与数值类型所能表示的范围有关。
  • @Mike Seymour,已经修复。
猜你喜欢
  • 1970-01-01
  • 2010-09-21
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
相关资源
最近更新 更多