如果两个值的数据类型是“double”。有没有办法在不使用比较运算符(如 if 或“?”)的情况下获得两个最大值。我只需要一个更快的方法。
问问题
728 次
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 的情况下使用整数比较会失败。
如果您的编译器知道FCMOVcc
x86 上的条件移动,您可以在不使用慢速分支指令的情况下获得两个浮点值的最大值。
于 2013-06-13T01:00:30.863 回答