1

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

4

2 回答 2

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,但这没关系!不过,这也可能溢出。

于 2013-06-13T00:33:50.770 回答
3

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

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

于 2013-06-13T01:00:30.863 回答