Algorithm 快速无除法平均

Algorithm 快速无除法平均,algorithm,language-agnostic,bit-manipulation,binary-search,Algorithm,Language Agnostic,Bit Manipulation,Binary Search,我有一个二进制搜索循环,它在执行路径中被多次命中 探查器显示,搜索的分割部分(根据搜索范围的高索引和低索引查找中间索引)实际上是搜索成本最高的部分,大约是搜索成本的4倍 (我认为)对于高效的二进制搜索来说,找到准确的中间值并不重要,只需找到一个在两个方向上都没有偏差的中间值 是否有一个小的旋转算法来代替mid=(低+高)/2 编辑:语言是C#,但是等价的位运算在任何语言中都是有效的(尽管它可能对性能没有好处),这就是为什么我不使用C#标记的原因 请注意,当整数溢出成为问题时,使用“(低+高)/2

我有一个二进制搜索循环,它在执行路径中被多次命中

探查器显示,搜索的分割部分(根据搜索范围的高索引和低索引查找中间索引)实际上是搜索成本最高的部分,大约是搜索成本的4倍


(我认为)对于高效的二进制搜索来说,找到准确的中间值并不重要,只需找到一个在两个方向上都没有偏差的中间值

是否有一个小的旋转算法来代替
mid=(低+高)/2

编辑:语言是C#,但是等价的位运算在任何语言中都是有效的(尽管它可能对性能没有好处),这就是为什么我不使用C#标记的原因


请注意,当整数溢出成为问题时,使用“(低+高)/2”进行中点计算。

您可以使用位移位,也可以克服可能的溢出问题:

low + ((high-low) >> 1)

然而,我必须承认,我期望现代编译器和解释器将2除法(或任何其他2的常数幂除法)作为位移位,所以不确定它是否真的有用-试试看。

如果我没记错的话,在某些情况下,使用数组的正中间实际上会比较慢。解决方案是随机选择将数组对分的索引。确定阵列中值的算法同样适用


我记不起确切的细节,但我记得在iTunes上听过的第6课。

这里是一个没有溢出问题的普通版本:

unsigned int average (unsigned int x, unsigned int y)
{
  return (x&y)+((x^y)>>1);
}

为了进一步扩展尼尔斯的答案,理查德·施罗佩尔发明了这个

项目23(施罗佩尔):

(A和B)+(A或B)=A+B=(A或B)+2(A和B)

(A和B)+(A或B)=A+B
因为
A和B
给出了(A和B之间)两个共享幂的和,
A或B
给出了共享幂和非共享幂,因此:

(A AND B) + (A OR B) = 
   (sum of shared powers of two) + 
   ((sum of shared powers of two) + (sum of unshared powers of two)) = 
     (sum of shared powers of two) + 
     ((sum of shared powers of two) + (sum of powers of two of A only) + 
     (sum of powers of two of B only)) = 
       ((sum of shared powers of two) + (sum of powers of two of A only)) + 
       ((sum of shared powers of two) + (sum of powers of two of B only)) 
= A + B. 
A异或B
给出了A和B之间不同位的映射。因此

A XOR B = (sum of powers of two of A only) + (sum of powers of two of B only). 
因此:

2(A AND B) + (A XOR B) = 
       ((sum of shared powers of two) + (sum of powers of two of A only)) + 
       ((sum of shared powers of two) + (sum of powers of two of B only)) 
= A + B.


尝试低+((高-低)/2)。这应该行得通,因为你只取两个数字的平均值。如果二进制搜索列表相当大,这将减少算法所花费的时间,因为高-低比高+低小得多。

数组有多大?你试过使用线性搜索吗?这真的不是语言不可知的东西——关于这种操作的速度的细节是非常特定于平台的。如果您处理的是一种动态类型的语言,则完全可能是在浮点数学中进行除法,或者使用了大整数结构。在大多数静态类型语言中,类似(low+high)/2的东西也会自动优化为add和算术右移。“只是中间附近的一个值,在两个方向上都没有偏差。”你的整数除以2不是已经有偏差了吗?我怀疑中点的发现是这里的瓶颈。整数除以2应编译为右移。高、低和中是否声明为整数?我很想看看你的整个二进制搜索程序。我认为我们在这里遗漏了一些东西。有这么大的偏差确实很奇怪,所以我也有兴趣看看整个程序。正确答案是+1,但我必须指出,“很多二进制搜索被破坏了”有点耸人听闻。更像是“很多二进制搜索实现都包含一个溢出错误,该错误发生在大量项目中。”看起来我在您发表此评论之前更新了文本。现在好点了吗?:)我和吉米在这件事上是一致的。。。我希望编译器已经在进行这种优化了。如果速度更快,我会感到非常惊讶。如果有一个好的编译器,速度应该不会更快,但最快的方法是尝试一下。经过基准测试,这比分区有显著(4倍)的性能提升。我用了蚂蚁分析器。我担心会变得太狡猾。你要确保你在最后把它们都击中。如果高和低之间的距离大于某个数字,可以随机化。哇。我喜欢!当然,我希望通常解决方案的加法、减法和移位速度至少会一样快。但是你在那里获得了重要的冷静点!在现代pc上,两个版本之间的性能差异不再造成差异。@Nils:是的,在现代CPU上,二进制搜索的不可预测分支是速度杀手。@nilspipenbrinck您能为解决方案添加一个解释吗。我的意思是它可以工作,但你是如何找到解决方案的?我怎么能理解呢?@baltusaj,嗯,不。我无法解释在评论的上下文中如何工作(没有时间)。然而,你可以把这当作一个问题来问。我相信这里的小捣蛋鬼会很乐意分享他们在这个话题上的知识。这和尼尔斯上面的一样,只是你改变了术语。完全等同于'09'的答案。@greybeard我自己想出了这个。
A XOR B = (sum of powers of two of A only) + (sum of powers of two of B only). 
2(A AND B) + (A XOR B) = 
       ((sum of shared powers of two) + (sum of powers of two of A only)) + 
       ((sum of shared powers of two) + (sum of powers of two of B only)) 
= A + B.