ChatGPT解决这个技术问题 Extra ChatGPT

“else if”比“switch() case”快吗? [复制]

这个问题在这里已经有了答案:在 C# 中使用 if/else 和 switch-case 有什么显着区别吗? (20 个回答) 2 年前关闭。

我是前 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”语句)。我应该把它们变成开关吗?

我不得不指出,如果你的代码有很多这样的结构,你可能在设计中没有充分利用多态性。
Switch 更快,但除非您对紧密循环进行超级优化,否则它没有任何意义。什么是 37 纳秒 vs 42 纳秒(组成数字)?
我想知道在案例级别使用逻辑时这有什么不同,例如(伪)switch(true) case a==0; case a>0; case a<0;
@Jacksonkr Java 不允许打开 boolean 类型的值。此外,case 表达式必须是常量。

G
Guffa

对于少数几项,差异很小。如果您有很多物品,您绝对应该使用开关。

如果一个开关包含五个以上的项目,则使用查找表或哈希列表来实现。这意味着所有项目都获得相同的访问时间,与 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 它可能会有些隐藏。
W
Wedge

你为什么在乎?

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 语句的主体进行小的改进可以带来巨大的性能提升。在设计时进行这样的思考可以帮助防止导致您不得不使用分析工具的问题。这是一个合法的问题,不应忽视。
M
Michael Klement

相信 this performance evaluation,switch case 更快。

这是结论:

结果表明 switch 语句比 if-else-if 梯形图执行得更快。这是由于编译器能够优化 switch 语句。在 if-else-if 梯形图的情况下,代码必须按照程序员确定的顺序处理每个 if 语句。但是,因为 switch 语句中的每个 case 都不依赖于较早的 case,所以编译器能够以提供最快执行速度的方式重新排序测试。


V
Vilx-

另一件需要考虑的事情:这真的是您的应用程序的瓶颈吗?在极少数情况下确实需要这种优化。大多数时候,你可以通过重新思考你的算法和数据结构来获得更好的加速。


S
Steven

Switch 通常比长长的 if 列表要快,因为编译器可以生成跳转表。列表越长,switch 语句对一系列 if 语句的影响就越好。


请注意,跳转表仅适用于(IIRC)连续值。编译器为复杂的非连续选项发出混合跳转表和 breq 的情况并不少见。
M
Marcello B.

我会说切换是要走的路,它既更快又更好的做法。

这是一个 link,它显示了比较两者的基准测试。


Ó
Ólafur Waage

应该不难测试,创建一个在 5 个数字之间切换或 ifelse 的函数,将 rand(1,5) 放入该函数并在计时时循环几次。


J
Joey

switch 通常由编译器翻译成查找表,如果可能的话。因此,查找任意案例是 O(1),而不是在找到您想要的案例之前实际进行一些案例比较。

因此,在许多情况下,if/else if 链会更慢。不过,根据您的案件受到打击的频率,这可能没有什么区别。


u
user308693

我不确定,但我相信其中一种或另一种的速度会根据您使用的编程语言而变化。

我通常更喜欢使用开关。这样代码更容易阅读。


有趣的是,我认为如果 else 更干净:DI 认为使用最易读的东西。
同样在这里。 'else if' 更容易阅读和书写。 switch case break 等等......那里的东西太多了。我对 Arduino 的基准测试显示“else if”更快。 github 上的这个人也是。 github.com/nezumi-tech/if_elseif_vs_switch_case_on_Arduino_Mega 我想这个问题的答案取决于您编写的代码。
j
jfclavette

从技术上讲,它们产生完全相同的结果,因此它们应该以几乎相同的方式进行优化。但是,与 ifs 相比,编译器使用跳转表优化 switch case 的可能性更大。

我在这里谈论一般情况。对于 5 个条目,假设您按频率对条件进行排序,为 if 执行的平均测试次数应少于 2.5。除非在一个非常紧凑的循环中,否则几乎不会成为写回家的瓶颈。


a
annakata

比 switch 的性能优势(相对轻微,但值得注意)更重要的是可读性问题。

与 if 链相比,我发现一个 switch 语句的意图和纯空格非常清晰。


A
AnnaR

简短回答:switch 语句更快

if 语句平均需要两次比较(在运行示例代码时)才能找到正确的子句。

无论您有多少不同的情况,switch 语句的平均比较次数都是 1。编译器/VM 将在编译时制作一个可能选项的“查找表”。

如果您经常运行此代码,虚拟机是否可以以类似的方式优化 if 语句?


m
mqp

由于 switch 语句表达了与 if / else 链相同的意图,但以更受限制、更正式的方式,您的第一个猜测应该是编译器将能够更好地优化它,因为它可以绘制更多关于代码条件的结论(即只有一个状态可能为真,被比较的值是原始类型等)当您比较两种相似的语言结构的运行时性能时,这是一个非常安全的一般事实。


U
User42590

http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.switch%28VS.71%29.aspx

switch 语句基本上是一个查找表,它具有已知的选项,if 语句类似于布尔类型。根据我的说法, switch 和 if-else 是相同的,但对于逻辑 switch 可以提供更好的帮助。而 if-else 也有助于阅读理解。