我有一段代码想要优化以提高可读性、性能和酷炫度。现在我有这个丑陋的东西:
if ( cond1 && cond2 && cond3 && !cond4)
{
// do something
}
else if ( cond1 && cond2 && !cond3 && cond4)
{
// do something
}
else if ( cond1 && !cond2 && cond3 && cond4)
{
// do something
}
else if (!cond1 && cond2 && cond3 && cond4)
{
// do something
}
else
{
// do something
}
其中 cond1
、cond2
、cond3
和 cond4
是在 block 之前初始化的 bool 值上面的代码。我想让它更快、更不丑陋、更酷。
我正在考虑这样做:
int val = (cond1 ? 0 : 1) + 2 * (cond2 ? 0 : 1) + 4 * (cond3 ? 0 : 1) + 8 * (cond4 ? 0 : 1);
if (val == 8)
{
// do something
}
else if (val == 4)
{
// do something
}
else if (val == 2)
{
// do something
}
else if (val == 1)
{
// do something
}
else
{
// do something
}
这行得通还是有缺陷?有没有更好的办法?在查看多种条件的不同组合时,实现预期结果的典型方法是什么?
最佳答案
您希望以一种或另一种方式将您的值放入位标志中。那就是你想要为每个条件设置或不设置整数类型。然后,您案例中的每个 4 位值都代表上述 ANDed 条件之一。之后,您可以使用 switch 语句。它可以说更具可读性,并且编译器通常可以将其优化为跳转表。也就是说,它只会将您的程序计数器偏移查找表中的某个值或类似的东西,您不再需要检查每个值的组合。通过这种方式,您对 ANDed 案例的检查变成了常数时间而不是线性的,也就是说,如果您再添加 4 个标志并且现在有 256 种组合而不是 16 种组合,那么这种方法将以大哦的方式同样快。或者,如果您不相信编译器会将 switch 语句设为跳转表,您可以使用 flags
值作为函数指针数组的索引自行完成。还可能值得注意的是,ORed 枚举大小写值在编译时被折叠或预先计算。
enum {
C1 = 0x1,
C2 = 0x2,
C3 = 0x4,
C4 = 0x8
};
unsigned flags = 0;
flags |= cond1 ? C1 : 0x0;
flags |= cond2 ? C2 : 0x0;
flags |= cond3 ? C3 : 0x0;
flags |= cond4 ? C4 : 0x0;
switch (flags) {
case 0: // !cond1 && !cond2 && !cond3 && !cond4
// do something
break;
case C1: // cond1 && !cond2 && !cond3 && !cond4
// do something
break;
case C2: // !cond1 && cond2 && !cond3 && !cond4
// do something
break;
case C1 | C2: // cond1 && cond2 && !cond3 && !cond4
// do something
break;
case C3: // !cond1 && !cond2 && cond3 && !cond4
// do something
break;
case C1 | C3: // cond1 && !cond2 && cond3 && !cond4
// do something
break;
case C2 | C3: // !cond1 && cond2 && cond3 && !cond4
// do something
break;
case C1 | C2 | C3: // cond1 && cond2 && cond3 && !cond4
// do something
break;
case C4: // !cond1 && !cond2 && !cond3 && cond4
// do something
break;
case C1 | C4: // cond1 && !cond2 && !cond3 && cond4
// do something
break;
case C2 | C4: // !cond1 && cond2 && !cond3 && cond4
// do something
break;
case C1 | C2 | C4: // cond1 && cond2 && !cond3 && cond4
// do something
break;
case C3 | C4: // !cond1 && !cond2 && cond3 && cond4
// do something
break;
case C1 | C3 | C4: // cond1 && !cond2 && cond3 && cond4
// do something
break;
case C2 | C3 | C4: // !cond1 && cond2 && cond3 && cond4
// do something
break;
case C1 | C2 | C3 | C4: // cond1 && cond2 && cond3 && cond4
; // do something
};
此外,这涵盖了所有组合。如果您只需要一些子集,请随意删除一些案例。编译器非常擅长优化 switch 语句。它可能比您可以自己推出的任何聪明的特殊情况算术技巧都要快。
enum {
C1 = 0x1,
C2 = 0x2,
C3 = 0x4,
C4 = 0x8
};
unsigned flags = 0;
flags |= cond1 ? C1 : 0x0;
flags |= cond2 ? C2 : 0x0;
flags |= cond3 ? C3 : 0x0;
flags |= cond4 ? C4 : 0x0;
switch (flags) {
case C1 | C2 | C3: // cond1 && cond2 && cond3 && !cond4
// do something
break;
case C1 | C2 | C4: // cond1 && cond2 && !cond3 && cond4
// do something
break;
case C1 | C3 | C4: // cond1 && !cond2 && cond3 && cond4
// do something
break;
case C2 | C3 | C4: // !cond1 && cond2 && cond3 && cond4
// do something
break;
default:
// do something
;
};
关于algorithm - 简化/优化一段查看条件组合的代码的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23162309/