我有一个带有两个条件的if语句(由OR运算符分隔),其中一个条件覆盖了+ 70%的情况,并且处理/执行的时间远远少于第二个条件,所以为了速度我只有在第一个条件的计算结果为false时才希望处理第二个条件。
如果我订购条件以便第一个条件(更快的条件)首先出现在if语句中 - 在满足这个条件的情况下并且评估为真是第二个条件甚至被处理?
if ( (condition1) | (condition2) ){
// do this
}
或者我是否需要将两个if语句嵌套到仅检查第二个条件(如果第一个条件的计算结果为false)?
if (condition1){
// do this
}else if (condition2){
// do this
}
我在PHP工作,但是,我认为这可能与语言无关。
答案 0 :(得分:9)
对于C,C ++,C#,Java和其他.NET语言,布尔表达式已经过优化,因此只要知道其他内容,就不会对其他内容进行评估。
进行混淆代码的一个老技巧是使用它来创建if语句,例如:
a || b();
如果“a”为真,则“b()”永远不会被评估,所以我们可以将其重写为:
if(!a)
b();
同样地:
a && b();
会变成
if(a)
b();
请注意,这仅适用于||和&&运营商。两个运营商|和&是按位或,和,分别,因此不是“优化”。
编辑: 正如其他人所提到的,尝试使用短路逻辑优化代码很少花费时间。
首先要明确,因为它更容易阅读和理解。此外,如果你试图过于聪明,对条款的简单重新排序可能会导致完全不同的行为而没有任何明显的原因。
其次,进行优化,但只能在计时和分析之后。太多的开发人员在没有分析的情况下进行过早优化。大多数时候它完全没用。
答案 1 :(得分:3)
几乎每种语言都进行短路评估。意味着第二个条件只有在非常必要的情况下才会被评估。为此,大多数语言使用双管道,||,而不是单管道,|。
答案 2 :(得分:3)
在C,C ++和Java中,声明:
if (condition1 | condition2) {
...
}
每次都会评估这两个条件,只有在整个表达式为真时才为真。
声明:
if (condition1 || condition2) {
...
}
仅当
condition2
为false时,才会评估condition1
。如果condition2是一个函数或另一个带有副作用的表达式,则差异很大。
||
案例与if
/ else
案例之间没有区别。
答案 3 :(得分:2)
我最近看到了很多这类问题 - 优化到第n级。
我认为在某些情况下这是有道理的:
在其他情况下,担心迭代或检查条件的“最快”方式是愚蠢的。而不是编写需要数百万次试验以查看任何可记录(但无关紧要)差异的测试,而不是注重清晰度。
当其他人(可能是你!)在一个月或一年内获取此代码时,最重要的是清晰度。
在这种情况下,您的第一个示例更短,更清晰,并且不需要您重复自己。
答案 4 :(得分:2)
根据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
}
?>
答案 5 :(得分:2)
短路不是为了优化。它的主要目的是避免调用不起作用的代码,从而导致可读的测试。例如:
if (i < array.size() && array[i]==foo) ...
请注意,如果i超出范围并使程序崩溃,则array [i]可能会获得访问冲突。因此,该计划肯定取决于评估的短路!
我认为这就是以这种方式编写表达式的原因,远远超过优化问题。
答案 6 :(得分:1)
虽然为了优化而使用短路通常是过度的,但使用它肯定有其他令人信服的理由。一个这样的例子(在C ++中)如下:
if( pObj != NULL && *pObj == "username" ) {
// Do something...
}
此处,正在依赖短路以确保在解除引用之前已分配pObj
。这比嵌套的if
语句简洁得多。
答案 7 :(得分:0)
由于这是标记语言不可知的,我会插话。对于Perl至少,第一个选项就足够了,我不熟悉PHP。它从左到右进行评估,并在条件满足后立即退出。
答案 8 :(得分:0)
在大多数具有良好优化的语言中,前者都可以正常工作。
答案 9 :(得分:0)
|
是PHP中的按位运算符。这并不完全是$a OR $b
。你会想要使用双管。是的,如上所述,PHP会进行短路评估。以类似的方式,如果&&
子句的第一个条件的计算结果为false,则PHP也不会评估该子句的其余部分。
答案 10 :(得分:0)
VB.net有两个精彩的表达方式叫做“OrElse”和“AndAlso”
OrElse会在第一次达到True评估时自行短路并执行您想要的代码。
If FirstName = "Luke" OrElse FirstName = "Darth" Then
Console.Writeline "Greetings Exalted One!"
End If
AndAlso会在第一次进行虚假评估时自行短路,而不会评估该区域内的代码。
If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
Console.Writeline "You are the one and only."
End If
我觉得这些都很有帮助。