如果两个值的数据类型是“double”。有没有办法在不使用比较运算符(例如if或“?”)的情况下获得最多两个。我只需要一种更快的方法。
答案 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
等条件移动,则可以在不使用慢速分支指令的情况下获得最多两个浮点值。