最多两个双数据类型值,不使用比较运算符

时间:2013-06-13 00:27:57

标签: c

如果两个值的数据类型是“double”。有没有办法在不使用比较运算符(例如if或“?”)的情况下获得最多两个。我只需要一种更快的方法。

2 个答案:

答案 0 :(得分:6)

  

我只需要更快的方法。

比比较更快?没门。比较只会生成高度优化的机器指令。不要看你如何改进。

但是,这里有一些你的乐趣的好奇心。

这是一种方式:

double max = 0.5 * (a + b + fabs(a - b));

证明:

a >= b => a - b >= 0 
       => |a - b| = a - b 
       => a + b + |a - b| = a + b + a - b = 2a 
       => 0.5 * (a + b + |a - b|) = a

a < b => a - b < 0 
      => |a - b| = b - a 
      => a + b + |a - b| = a + b + b - a = 2b 
      => 0.5 * (a + b + |a - b|) = b

注意这有一个弱点:它可能会溢出。

这是另一个:

double difference = a - b;
double sign = ((int)difference)>>63) & 1;
double max = a - difference * sign;

这里的直觉显而易见。我们想要计算差异的符号(不使用比较),并使用该符号来计算最大值

证明:

a > b => a - b >= 0
      => difference >= 0
      => sign = 0
      => max = a - difference * sign = a - (a - b) * 0 = a
      => max = a

a < b => a - b < 0
      => difference < 0
      => sign = 1
      => max = a - difference * sign = a - (a - b) * 1 = a - a + b = b
      => max = b

注意,0有两个可能的标志来自+ 0d和-0d,但没关系!不过,这也可能会溢出。

答案 1 :(得分:3)

32位或64位CPU上的所有现代浮点单元每个时钟周期都可以产生(至少)一个加法结果,延迟时间为几个时钟周期。浮点比较具有与浮点加法相同的性能。因此,您无法通过使用其他浮点指令的组合来加速浮点比较,并且在NaN的情况下使用整数比较失败。

如果编译器知道x86上的FCMOVcc等条件移动,则可以在不使用慢速分支指令的情况下获得最多两个浮点值。