“else if”比“switch() case”快吗? [复制]
Posted
技术标签:
【中文标题】“else if”比“switch() case”快吗? [复制]【英文标题】:Is "else if" faster than "switch() case"? [duplicate] 【发布时间】:2010-10-20 13:11:35 【问题描述】:我是前 Pascal 人,目前正在学习 C#。 我的问题如下:
下面的代码是不是比切换快?
int a = 5;
if (a == 1)
....
else if(a == 2)
....
else if(a == 3)
....
else if(a == 4)
....
else
....
还有开关:
int a = 5;
switch(a)
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
case 4:
...
break;
default:
...
break;
哪个更快?
我在问,因为我的程序具有类似的结构(很多很多“else if”语句)。 我应该把它们变成开关吗?
【问题讨论】:
我不得不指出,如果你的代码有很多这样的结构,你可能在设计中没有充分利用多态性。 见***.com/questions/445067/if-vs-switch-speed 切换速度更快,但除非您对紧密循环进行超级优化,否则它没有任何意义。什么是 37 纳秒 vs 42 纳秒(组成数字)? 我想知道在案例级别使用逻辑时这有什么不同,例如(伪)switch(true) case a==0; case a>0; case a<0;
等
@Jacksonkr Java 不允许切换boolean
类型的值。此外,case
表达式必须是常量。
【参考方案1】:
对于少数几个项目,差异很小。如果您有很多项目,您绝对应该使用开关。
如果一个开关包含五个以上的项目,它是使用查找表或哈希列表来实现的。这意味着与 if:s 列表相比,所有项目都获得相同的访问时间,其中最后一个项目需要更多时间才能到达,因为它必须首先评估每个先前的条件。
【讨论】:
是的,但是使用 if-else-if 链,您可以根据条件为真的可能性对条件进行排序。 是的,但是前 4-5 个案例必须捕获非常接近 100% 的事件才能弥补较慢的事件。 大多数现代编译器不应该优化深度 if/else if/else if/else if 决策点作为切换/跳转表吗?也就是说;这应该没关系,编译器会优化它,为什么不写最可读的代码呢? @Dean J:是的,通常你应该编写最易读的代码,即使性能有所不同。如果您需要优化代码,它可能仍然会有所作为。为了让编译器按照您描述的方式优化代码,它必须对值有更多的了解,即知道多次读取值是否有任何副作用,因为将代码更改为开关只会读取一次值。 从我的角度来看 switch 也比 if-elseif 链更具可读性。这也容易出现混淆if-else等错误;如果别的;其中还有其他副作用。使用 switch,您会立即看到 n-fork,而使用连续的 if-else-if-else 可能会有些隐藏。【参考方案2】:你为什么在乎?
99.99% 的情况下,您不必在意。
这类微优化不太可能影响代码的性能。
另外,如果您需要关心,那么您应该对您的代码进行性能分析。在这种情况下,找出 switch case 和 if-else 块之间的性能差异将是微不足道的。
编辑:为了清楚起见:实现更清晰和更易于维护的设计。通常,当遇到巨大的 switch-case 或 if-else 块时,解决方案是使用多态性。找到正在改变的行为并将其封装起来。我以前不得不处理像这样巨大、丑陋的 switch case 代码,而且通常简化起来并不难。但是哦,太令人满意了。
【讨论】:
我绝对不同意。您绝对应该始终关心,而不是因为性能,但这也会影响代码的可读性和可维护性。而且,正如其他人所提到的,您可能会考虑更好地利用多态性。 哦,我同意您应该始终关心可读性和可维护性。重写一个巨大的 switch/case 块的正确方法可能是多态性(顺便说一下,它可能稍微慢一些,但你不应该关心)。宏观优化(好的设计)总是比微观优化(更快的语句)更好。 @GrahamS,这有点用词不当。虚拟机可以和“真实”的一样快……尤其是因为运行时可以比编译器更好地优化,因为它可以测量实际需要优化的内容。 PS:我对博尔顿迷宫的 java 解决方案需要 0.03375655565 秒。公布的获胜 C# 解决方案需要 0.166 秒,C++ 以 429.46 秒位居第二,找到错误答案。而 CLR 天生就很慢?嗯...我不这么认为,蒂姆 ;-) 那种“你永远不需要关心,因为性能永远不是问题”的想法。任何程序员怎么能考虑到这一点?作为一名程序员,您需要知道引擎盖下发生了什么,了解编译器并充分利用它,因为有一天那些额外的 MS 可能会挽救您的一天。来自 C++,我在 C# 中看到了很多这样的想法和行为,这很可惜。宁可回答他的问题,然后无视它。 考虑一个更一般的情况,您正在编写一个将被调用 >100k 次的函数。我倾向于称这些“乘数”。例如,递归函数的 for 循环中的 if 语句具有来自循环和函数的 2 个乘法器。对 if 语句主体的一个小改进可以带来巨大的性能提升。在设计时进行这样的思考可以帮助防止导致您不得不使用分析工具的问题。这是一个合法的问题,不应忽视。【参考方案3】:相信this performance evaluation,switch case 更快。
这是结论:
结果表明 switch 语句比 if-else-if 梯形图执行得更快。这是由于编译器能够优化 switch 语句。在 if-else-if 梯形图的情况下,代码必须按照程序员确定的顺序处理每个 if 语句。但是,由于 switch 语句中的每个 case 都不依赖于较早的 case,编译器能够以提供最快执行速度的方式重新排序测试。
【讨论】:
【参考方案4】:要考虑的另一件事:这真的是您的应用程序的瓶颈吗?在极少数情况下确实需要这种优化。大多数情况下,您可以通过重新考虑算法和数据结构来获得更好的加速。
【讨论】:
【参考方案5】:Switch 通常比长长的 if 列表更快,因为编译器可以生成跳转表。列表越长,switch 语句优于一系列 if 语句。
【讨论】:
请注意,跳转表仅适用于 (IIRC) 连续值。编译器为复杂的非连续选项发出混合跳转表和 breq 的情况并不少见。【参考方案6】:我想说切换是要走的路,它是更快更好的做法。
这是一个link,显示了比较两者的基准测试。
【讨论】:
【参考方案7】:应该不难测试,创建一个在 5 个数字之间切换或 ifelse 的函数,将 rand(1,5) 放入该函数并在计时时循环几次。
【讨论】:
【参考方案8】:switch
通常由编译器翻译成查找表,如果可能的话。因此,查找任意案例是 O(1),而不是在找到您想要的案例之前实际进行一些案例比较。
所以在很多情况下if
/else if
链会更慢。不过,这取决于您的案件受到打击的频率,这可能没有什么区别。
【讨论】:
【参考方案9】:从技术上讲,它们产生完全相同的结果,因此它们应该以几乎相同的方式进行优化。但是,编译器使用跳转表优化 switch case 的机会比 ifs 多。
我在这里谈论的是一般情况。对于 5 个条目,假设您按频率对条件进行排序,则为 ifs 执行的平均测试次数应小于 2.5。除非在一个非常紧凑的循环中,否则几乎不会成为写回家的瓶颈。
【讨论】:
【参考方案10】:比 switch 的性能优势(相对轻微,但值得注意)更重要的是可读性问题。
我发现与 if 链相比,switch 语句的意图和纯空格非常清晰。
【讨论】:
【参考方案11】:我不确定,但我相信其中一种或另一种的速度会根据您使用的编程语言而变化。
我通常更喜欢使用开关。这样代码更容易阅读。
【讨论】:
有趣,我认为如果其他更干净:D 我认为使用最易读的东西。【参考方案12】:简答:switch 语句更快
if 语句平均需要两次比较(运行示例代码时)才能找到正确的子句。
无论您有多少不同的情况,switch 语句的平均比较次数都将为 1。编译器/VM 将在编译时制作一个可能选项的“查找表”。
如果你经常运行这段代码,虚拟机能否以类似的方式优化 if 语句?
【讨论】:
【参考方案13】:由于switch
语句表达了与if
/ else
链相同的意图,但是以更严格、更正式的方式,您的第一个猜测应该是编译器将能够更好地优化它,因为它可以对代码中的条件得出更多结论(即,只有一个状态可能为真,被比较的值是原始类型等)当您在运行时比较两种相似的语言结构时,这是一个非常安全的普遍事实性能。
【讨论】:
【参考方案14】:见 http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.switch%28VS.71%29.aspx
switch 语句基本上是一个查找表,它具有已知的选项,if 语句类似于布尔类型。根据我的说法, switch 和 if-else 是相同的,但对于逻辑 switch 可以提供更好的帮助。而 if-else 也有助于阅读理解。
【讨论】:
以上是关于“else if”比“switch() case”快吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为什么switch...case语句比if...else执行效率高