是否有“如果 A、B 和 C 都等于 D”的简写?在我现在所处的场景中,我实际上只对查看它们是否都相等感兴趣,而不是它们的实际值,所以“如果 A、B、C 和 D 相同”的东西也有效。
6 回答
该问题被标记为 C,但如果允许 C++11,您可以定义all_equal
如下:
template <typename T1>
inline bool all_equal(T1&& val) {
return true;
}
template <typename T1, typename T2, typename... Ts>
inline bool all_equal(T1&& val1, T2&& val2, Ts&&... rest) {
return val1 == val2 && all_equal(std::forward<T2>(val2), std::forward<Ts>(rest)...);
}
示例用法:
all_equal(3); // true
all_equal(3, 3); // true
all_equal(3, 4); // false
all_equal(x, y, z); // would be expanded to 'x == y && y == z'
参数的数量没有限制。
如果你想坚持使用 C,你可以使用变长参数列表,但我不推荐它。
您不太可能遇到这可能是速度限制的情况。然而,通常,最小化循环中的分支是最快的。
我会做
!(a^b | b^c | c^d)
我怀疑位运算符|
会比 wildplasser 答案中的短路更快||
,至少当每次执行循环时结果都不相同时不要假设。如果它真的很重要,请尝试两者并进行测量。
虽然它的语法很短
短路异或技巧:
int abcd(unsigned aa, unsigned bb, unsigned cc, unsigned dd)
{
#define FOUR_UNEQUAL(a,b,c,d) ((a^b^c^d) || (a^b) || (c^d) || (b^c)) ? 1 : 0
return FOUR_UNEQUAL(aa,bb,cc,dd);
}
生成的程序集(GCC 4.6.1-9ubuntu3):
type abcd, @function
abcd:
.LFB23:
.cfi_startproc
movl %esi, %eax
xorl %edi, %eax
xorl %edx, %eax
cmpl %ecx, %eax
jne .L7
cmpl %esi, %edi
jne .L7
cmpl %ecx, %edx
setne %al
cmpl %edx, %esi
setne %dl
orl %edx, %eax
movzbl %al, %eax
ret
.p2align 4,,10
.p2align 3
.L7:
movl $1, %eax
ret
.cfi_endproc
而且,如前所述,速度增益是微不足道的(如果有的话)。
你可以定义一个宏来做到这一点:
#DEFINE ARE_ALL_EQUALS(A, B, C, D) (((A) == (B)) && ((B) == (C)) && ((C) == (D)))
但要注意 B 和 C 的多重评估。
你可以定义一个宏
#define ALL_EQUAL(A, B, C, D) ((A) == (B)) && ((B) == (C)) && ((C) == (D))
但我看不出比通常的东西有任何优势。
也许“最快”的方法是比较对,然后检查对的结果:
(A == B) && (C == D) && (A == C)
正如 OP 所指出的那样。对于更多元素,工作对,并在完整的二叉树中组合结果。可能会尽可能地重新排序,以便&&
平均尽早失败。无论如何,这是一个非常专业的操作(如果我曾经做过类似的事情,我不记得了),因此为此提供额外的符号可能会比获得的伤害更大。
与往常一样:首先编写最易读的代码,然后在测量结果表明值得的情况下进行性能评估。人工时间(编写、调试、维护代码)比计算机运行它的时间更有价值,除非在极少数情况下。