很难给出一个公正的“更好”的解决方案(在哪个方面更好 - 代码行数,可读性,执行速度,机器代码指令字节数等?),但由于您在这种情况下询问执行速度,我们可以专注于此。
您可以引入建议的变量,并在答案已知后将其用于将条件减少到简单的小于条件。小于条件在大多数体系结构上可以轻松地转换为两个机器代码指令(例如,在Intel IA-32上是CMP
(比较)后跟JL
(如果小于则跳转)或JNL
(如果不小于则跳转)。有了一点运气,编译器会注意到(或者您可以自己做,但我更喜欢在每个地方都有相同模式的清晰度),即trues < 2
将始终在前两个if()
语句中成立,并将其优化掉。
int trues = 0;
if (trues < 2 && condition1) trues++;
if (trues < 2 && condition2) trues++;
if (trues < 2 && condition3) trues++;
// ...
if (trues >= 2)
{
// do something
}
一旦答案已知,这将把可能复杂的
conditionN
评估简化为一个简单的小于比较,因为大多数语言都具有布尔短路行为。
如果您的语言允许将布尔条件转换为整数,则另一种可能的变体是利用它来减少源代码行数。但是仍然需要评估每个条件。
if( (int)(condition1)
+ (int)(condition2)
+ (int)(condition3)
>= 2)
{
// do something
}
这个做法的前提是将布尔值FALSE转换为整数时结果为0,而将TRUE转换为1。你也可以使用条件运算符达到相同的效果,但要注意它可能会引入额外的分支。
if( ((condition1) ? 1 : 0)
+ ((condition2) ? 1 : 0)
+ ((condition3) ? 1 : 0)
>= 2)
{
// do something
}
根据编译器优化器的智能程度,它可能能够确定一旦任何两个条件都评估为true,则整个条件将始终评估为true,并基于此进行优化。
请注意:
除非你已经对代码进行了分析并确定这是罪魁祸首,否则这很可能是过早优化的情况。
始终要让代码首先易于人类程序员阅读,其次才是计算机执行速度快,除非你能证明你正在查看的
特定代码片段是一个
实际存在的性能瓶颈。
学习如何使用分析器并将其充分利用。请记住,在大多数情况下,程序员的时间比 CPU 时间更昂贵,而巧妙的技术需要更长时间来解析维护程序员。
另外,编译器是非常聪明的软件;有时它们实际上会检测到所写代码的
意图,并能够使用特定的结构使这些操作更快,但这取决于它能否确定你试图做什么。一个完美的例子是使用中间变量交换两个变量,在 IA-32 上可以使用
XCHG
消除中间变量,但编译器必须能够确定你实际上正在这样做,而不是
某些情况下可能导致其他结果的聪明方法。
由于绝大多数非显式一次性使用的软件都在维护模式下度过了它的大部分生命周期(而且很多一次性使用的软件在其预期的最佳使用日期之后仍然活跃),因此优化可维护性是有意义的,除非这会带来其他方面无法接受的代价。当然,如果你在一个紧密的循环内评估这些条件一万亿次,有针对性的优化可能是有意义的。但分析器将告诉您哪些代码部分需要从性能角度更加仔细地审查,这意味着您可以避免不必要地使代码复杂化。
在上述警告的前提下,我最近一直在编写代码并进行更改,这些更改乍一看几乎肯定会被认为是过早的详细优化。如果您需要高性能,并使用分析器确定代码的瓶颈部分,则这些优化不算过早。(但是,根据具体情况,它们仍可能是不明智的。)
condition1
,condition2
和condition3
是int
变量吗?我问这个问题是因为它们在你的问题中看起来像变量。 - jxh