【问题标题】:if statement condition optimisationif 语句条件优化
【发布时间】:2010-09-07 06:56:32
【问题描述】:

我有一个带有两个条件的 if 语句(由 OR 运算符分隔),其中一个条件涵盖 +70% 的情况,并且比第二个条件花费的时间要少得多,所以为了速度我只希望在第一个条件的计算结果为 false 时处理第二个条件。

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

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

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

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

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

【问题讨论】:

    标签: php language-agnostic conditional


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

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

          a || b();
          

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

          if(!a)
              b();
          

          同样:

          a && b();
          

          会变成

          if(a)
              b();
          

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

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

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

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

          【讨论】:

            【解决方案5】:

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

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

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

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

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

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

            【讨论】:

              【解决方案6】:

              根据this article 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
              }
              
              ?>
              

              【讨论】:

                【解决方案7】:

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

                if (condition1 | condition2) {
                  ...
                }
                

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

                声明:

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

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

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

                【讨论】:

                  【解决方案8】:

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

                  【讨论】:

                    【解决方案9】:

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

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

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

                    【讨论】:

                      【解决方案10】:

                      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
                      

                      我觉得这两个都有帮助。

                      【讨论】:

                      • 就是这样 ||和 && 分别在大多数其他语言中。
                      【解决方案11】:

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

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

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

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

                      【讨论】:

                        猜你喜欢
                        • 2017-12-24
                        • 2019-03-10
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-04-12
                        • 2011-05-18
                        相关资源
                        最近更新 更多