找到三重中间值的最快方法?

2022-08-31 21:05:36

给定是一个由三个数值组成的数组,我想知道这三个数值的中间值。

问题是,找到三者中间的最快方法是什么?

我的方法是这种模式 - 因为有三个数字,所以有六个排列:

if (array[randomIndexA] >= array[randomIndexB] &&
    array[randomIndexB] >= array[randomIndexC])

如果有人能帮助我找到一种更优雅更快捷的方法,那就太好了。


答案 1

这里有一个使用最小/最大和没有分支(https://stackoverflow.com/a/14676309/2233603)的答案。实际上,4分钟/最大操作足以找到中位数,不需要异或:

median = max(min(a,b), min(max(a,b),c));

虽然,它不会给你中位数的指数...

所有案例的细分:

a b c
1 2 3   max(min(1,2), min(max(1,2),3)) = max(1, min(2,3)) = max(1, 2) = 2
1 3 2   max(min(1,3), min(max(1,3),2)) = max(1, min(3,2)) = max(1, 2) = 2
2 1 3   max(min(2,1), min(max(2,1),3)) = max(1, min(2,3)) = max(1, 2) = 2
2 3 1   max(min(2,3), min(max(2,3),1)) = max(2, min(3,1)) = max(2, 1) = 2
3 1 2   max(min(3,1), min(max(3,1),2)) = max(1, min(3,2)) = max(1, 2) = 2
3 2 1   max(min(3,2), min(max(3,2),1)) = max(2, min(3,1)) = max(2, 1) = 2

答案 2

如果硬件可以在没有分支的情况下回答最小和最大查询,则可以在没有分支的情况下回答查询(当今大多数CPU都可以这样做)。

运算符 ^ 表示按位异或。

Input: triple (a,b,c)
1. mx=max(max(a,b),c)
2. mn=min(min(a,b),c)
3. md=a^b^c^mx^mn
4. return md

这是正确的,因为:

  • 异或是可交换和联想的
  • 等位上的异或产生零
  • 零的异或不会改变位

应为整型/浮点型选择适当的最小值/最大值函数。如果只存在正浮点数,则可以直接在浮点表示上使用整数最小值/最大值(这可能是可取的,因为整数运算通常更快)。

在硬件不支持最小值/最大值的不太可能的情况下,可以执行如下操作:

max(a,b)=(a+b+|a-b|)/2
min(a,b)=(a+b-|a-b|)/2

但是,在使用浮点运算时,这是不正确的,因为确切的最小值/最大值是必需的,而不是接近它的东西。幸运的是,浮动最小值/最大值在硬件中已经支持了很长时间(在x86上,从Pentium III及更高版本)。