我有一段代码,我想优化可读性、性能和酷度。现在我有一个丑陋的东西:
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
是在上述代码块之前初始化的布尔值。我想让它变得更快,不那么丑陋,更酷。
我正在考虑这样做:
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
}
这是有效的还是有缺陷的?有没有更好的方法?在查看多个条件的不同组合时,实现预期结果的典型方法是什么?
发布于 2014-04-19 05:20:26
好的,最令人愉快的方式可能是
if(cond1 + cond2 + cond3 + cond4 == 3)
{
if(!cond1)
{
// do something
}
else if(!cond2)
{
// do something
}
else if(!cond3)
{
// do something
}
else // !cond4
{
// do something
}
}
else
{
// do something
}
不过,我对那些不在数组中的值很谨慎。
发布于 2014-04-19 09:36:07
无论以何种方式,您都希望将值放入位标志中。也就是说,您需要为每个条件设置一个位或不设置为整数类型。那么在你的例子中,每个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
;
};
发布于 2014-04-19 05:15:15
将最有可能为假的条件放在左边,如果不检查其余条件,它将继续执行另一个条件,因此您在所谓的短路中获得了性能收益
https://stackoverflow.com/questions/23162309
复制相似问题