5

我有一个带有两个条件(由 OR 运算符分隔)的 if 语句,其中一个条件涵盖 +70% 的情况,并且处理/执行的时间比第二个条件少得多,所以为了速度我只想要如果第一个条件评估为假,则要处理第二个条件。

如果我对条件进行排序,以便第一个条件(较快的条件)首先出现在 if 语句中 - 在满足此条件并评估为 true 的情况下,是否甚至处理了第二个条件?

if ( (condition1) | (condition2) ){
  // do this
}

或者我是否需要嵌套两个 if 语句以仅在第一个条件为 false 时检查第二个条件?

if (condition1){
  // do this
}else if (condition2){
  // do this
}

我正在使用 PHP,但是,我认为这可能与语言无关。

4

11 回答 11

9

对于 C、C++、C#、Java 和其他 .NET 语言,布尔表达式进行了优化,以便在知道足够多的情况下立即评估其他内容。

进行混淆代码的一个老技巧是使用它来创建 if 语句,例如:

a || b();

如果 "a" 为真,则 "b()" 永远不会被计算,所以我们可以将其重写为:

if(!a)
    b();

同样:

a && b();

会成为

if(a)
    b();

请注意,这仅对 || 有效。和 && 运算符。两个运算符 | 和 & 分别是按位或,并且和,因此不是“优化”的。

编辑:正如其他人所提到的,尝试使用短路逻辑优化代码很少花费时间。

首先要清楚,因为它更容易阅读和理解。此外,如果您尝试过于聪明,则对术语进行简单的重新排序可能会导致完全不同的行为而没有任何明显的原因。

其次,进行优化,但仅在计时和分析之后。太多的开发人员在没有分析的情况下进行了过早的优化。大多数时候它完全没用。

于 2008-08-29T18:27:35.003 回答
3

几乎每种语言都会进行短路评估。这意味着仅在绝对必要时才评估第二个条件。为此,大多数语言使用双管道 ||,而不是单管道 |。

http://en.wikipedia.org/wiki/Short-circuit_evaluation

于 2008-08-29T18:24:25.310 回答
3

在 C、C++ 和 Java 中,声明:

if (condition1 | condition2) {
  ...
}

每次都会评估这两个条件,并且仅在整个表达式为真时才为真。

该声明:


if (condition1 || condition2) {
  ...
}

condition2只有当condition1为假时才会评估。如果 condition2 是一个函数或另一个具有副作用的表达式,则差异是显着的。

||但是, case 和if/ case之间没有区别else

于 2008-08-29T18:34:25.410 回答
2

我最近看到了很多这类问题——优化到第 n 级。

我认为在某些情况下这是有道理的:

  1. 计算条件 2 不是常数时间运算
  2. 您严格要求出于教育目的-您想知道语言是如何工作的,而不是为了节省 3us。

在其他情况下,担心迭代或检查条件的“最快”方式是愚蠢的。与其编写需要数百万次试验才能看到任何可记录(但微不足道)的差异的测试,不如专注于清晰度。

当其他人(可能是您!)在一个月或一年内收到此代码时,最重要的是清晰。

在这种情况下,您的第一个示例更短、更清晰,并且不需要您重复自己。

于 2008-08-29T18:32:30.280 回答
2

根据这篇文章PHP 进行短路评估,这意味着如果满足第一个条件,则甚至不评估第二个条件。它也很容易测试(来自文章):

<?php
/* ch06ex07 – shows no output because of short circuit evaluation */

if (true || $intVal = 5) // short circuits after true
{

echo $intVal; // will be empty because the assignment never took place
}

?>
于 2008-08-29T18:32:45.273 回答
2

短路不是为了优化。它的主要目的是避免调用不起作用的代码,但会导致可读的测试。例子:

if (i < array.size() && array[i]==foo) ...

请注意,如果 i 超出范围并导致程序崩溃,则 array[i] 很可能会出现访问冲突。所以这个程序肯定是靠短路来评价的!

我相信这就是以这种方式编写表达式比优化问题更频繁的原因。

于 2008-09-16T21:48:52.090 回答
1

虽然出于优化目的使用短路通常是矫枉过正,但肯定还有其他令人信服的理由来使用它。一个这样的例子(在 C++ 中)如下:

if( pObj != NULL && *pObj == "username" ) {
    // Do something...
}

在这里,依靠短路来确保pObj在取消引用之前已分配。这比嵌套if语句要简洁得多。

于 2008-08-29T22:00:55.757 回答
0

由于这是标记为语言不可知的,我会插话。至少对于 Perl,第一个选项就足够了,我不熟悉 PHP。它从左到右进行评估,并在满足条件后立即退出。

于 2008-08-29T18:22:35.890 回答
0

在大多数优化良好的语言中,前者可以正常工作。

于 2008-08-29T18:26:30.000 回答
0

|是 PHP 中的位运算符。这并不意味着$a OR $b,确切地说。你会想要使用双管。是的,如前所述,PHP 进行短路评估。以类似的方式,如果&&子句的第一个条件的计算结果为 false,PHP 也不会计算子句的其余部分。

于 2008-08-29T18:45:18.737 回答
0

VB.net 有两个奇妙的表达方式,叫做“OrElse”和“AndAlso”

OrElse 将在第一次达到 True 评估时自行短路并执行您想要的代码。

If FirstName = "Luke" OrElse FirstName = "Darth" Then
   Console.Writeline "Greetings Exalted One!"
End If

AndAlso 将在第一次进行 False 评估时自行短路,而不评估块内的代码。

If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
   Console.Writeline "You are the one and only."
End If

我觉得这两个都有帮助。

于 2008-08-29T22:06:06.337 回答