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

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

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

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

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

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

有帮助吗?

解决方案

对于 C、C++、C#、Java 和其他 .NET 语言,布尔表达式经过优化,以便一旦已知足够的信息,就不再评估其他任何内容。

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

a || b();

如果“a”为真,则“b()”永远不会被求值,因此我们可以将其重写为:

if(!a)
    b();

类似地:

a && b();

会成为

if(a)
    b();

请注意 这仅对||有效和&&操作员。两个操作员| &&是位或分别,并且分别是“优化”的。

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

首先要清晰,因为它更容易阅读和理解。另外,如果你试图变得太聪明,对术语的简单重新排序可能会导致毫无明显原因的截然不同的行为。

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

其他提示

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

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

在 C、C++ 和 Java 中,语句:

if (condition1 | condition2) {
  ...
}

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

该声明:


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

会评价 condition2 除非 condition1 是假的。如果 condition2 是一个函数或另一个具有副作用的表达式,则差异很显着。

但是,两者之间没有区别 || 案例和 if/else 案件。

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

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

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

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

当其他人(可能是你!)在一个月或一年内拿起这段代码时,最重要的是清晰度。

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

根据 本文 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
}

?>

短路并不是为了优化。它的主要目的是避免调用无法工作的代码,但会产生可读的测试。例子:

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

请注意,如果 i 超出范围,则 array[i] 很可能会发生访问冲突并使程序崩溃。所以这个程序肯定是依赖于短路评估!

我相信这就是以这种方式编写表达式的原因,而不是优化问题。

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

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

这里,依靠短路来确保 pObj 在解除引用之前已被分配。这比嵌套要简洁得多 if 声明。

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

在大多数经过适当优化的语言中,前者可以很好地工作。

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

VB.net 有两个美妙的表达式,称为“OrElse”和“AndAlso”

否则,它会在第一次达到 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

我发现这两者都有帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top