if/else条件判断是否比switch高,有多个判断应该怎么选择?

2010-11-10 01:45:36

6 Answers

需要分两种情况讨论:
一.若是switch(x)中的x能静态确定,两者效率一样。我们看下反汇编代码:
 By 5lulu.com
 By 5lulu.com
switch和if/else两者都是push、push、push、call的形式,即传递三个参数,第一个为:"%d,%d",第二个为:a的值,第三个为b的值。所以效率一样。

二.若条件得动态确定,也得分两种情况讨论:
1.当条件不多时,两者效率非常接近,看下图:
 By 5lulu.com
可以看见判断a=1、2、3的过程,每次dec eax(减1),然后jz short xxxx。也就是先比较是否等于3,再比较是否等于2,最后判断是否为1。都是判断后再减1与下个条件比较的。
if/else的实现如下图:
 By 5lulu.com
看见cmp edi,1和cmp edi,2了吗,也就是先与1比较,再与2比较,都不相等就是3了。cmp比较是做减法,先减1,再减2。
所以,两者几乎没区别。要说区别,switch多了一次判断,if/else有个减2。

2.当条件很多时,switch比if/else效率高。因为switch实现使用跳转表实现的,条件多的甚至用2、3级跳转表实现。
 
看见“jmp ds:off_40108C[eax4] ; switch jump”这句了吗,eax是switch(x)中的x。“dd offset loc_xxxxxx”这些就是跳转表,存放的是一个一个case:地址。所以是通过jmp ds:off_40108C[eax4]直接跳转过去的(基址+变址寻址)。
 
可以看见if/else仍然采用cmp xxx,1 jnz xxx、cmp xxx,2 jnz xxx、cmp xxx,3 jnz xxx...的方式实现的。
所以当条件很多时,switch比if/else效率高。

2010-11-10 04:14:48

if else是一条比较指令,需要遍历条件分支直到命中条件

而swtich是一张地址表,而只需访问对应索引号的表项就能定位分支,所以switch有点以空间换时间的意思。

用优点来描述一下就明白了:

  1. switch优点

当分支较多时,用switch的效率是很高的。因为switch是随机访问的,就是确定了选择值之后直接跳转到那个特定的分支,但是if else是遍历所以得可能值,知道找到符合条件的分支。如此看来,switch的效率确实比if else要高的多。

但是case常量分布范围很大但实际有效值又比较少的情况,switch的空间利用率将变得很低。

  1. if优点

switch只能处理常量的情况,对非常量的情况是无能为力的。像a > 1 && a < 100,这种表达式是无法使用switch的,只能用if else。所以if else能应用于更多的场合。

2010-11-10 05:07:56

这个不一定的,两个的用法都不一样,

一般if是写一个条件,switch是列举一些值来判断,看你需要哪种类型的,这两个一般没有说谁效率高的,一般选择用if来写,如果是像那个经典的例子判断分数段来显示优良中差的,那么肯定是用switch方便多了,

另外if可以判断更复杂的逻辑,进行范围判断等,switch在分支较多时的效率会高很多。

2010-11-10 06:56:29

switch直接查表跳转,比较高效,php的某个版本的性能提升就是对指令使用类似的技术替换原来的逐个比较;
但是只对大量的case分支+频繁执行才会有明显效果,所以不符合这个情况的就不用纠结了,而且if/else可比switch更动态。

2010-11-10 08:30:35

对于switch(x)和if(x),两者孰快孰慢取决于语句x在编译和运行期的情况。

  1. 如果x在编译期就能计算出来,那么运行的时候速度上就看不到区别,都是一个跳转语句,编译器进行了优化处理。
  2. 如果x需要根据运行时的情况计算然后进行处理,那么两者有可能有差别,但是分情况
2.1 如果x的结果是很简单的一个数字,字符,或者其他内置数据类型数据,那么两者的运行速度一样,都是进行判断然后跳转。 2.2 如果x需要进行复杂的计算(这真是if的长处,switch是没法做到的),那么if语句做计算的时间就是比switch多出的时间。

因此,从总体情况来看,if花费的时间 >= switch花费的时间。但是从语法角度来说,if语句的功能要比switch要强,switch算是一种特殊情况下的经过优化的if

2010-11-10 09:41:49

Switch 相当于键值对应的HashMap,ifelse相当于Array,前者是以key为查询条件,直接定位;后者是相当于写了个for循环,遍历了一遍所有条件。

2010-11-10 11:11:36
您不能回答该问题或者回答已经关闭!

相关文章推荐

  • C#中using指令的几种用法

    using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到

  • C#实例解析适配器设计模式

    将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作

  • 使用托管C++粘合C#和C++代码(二)

    本文实现一下C++代码调用C#代码的过程。我构造一个简单并且直观的例子:通过C++ UI 触发C# UI.

  • C#开发高性能Log Help类设计开发

    项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多

  • Async和Await使异步编程更简单

    C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作

  • C#开发中的反射机制

    反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等

  • C#运行时相互关系

    C#运行时相互关系,包括运行时类型、对象、线程栈和托管堆之间的相互关系,静态方法、实例方法和虚方法的区别等等

  • C#协变和逆变

    “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型,“逆变”则是指能够使用派生程度更小的类型

  • C#基础概念之延迟加载

    延迟加载(lazy load)是Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作

  • 使用托管C++粘合C#和C++代码(一)

    C#在xml读写,数据库操纵,界面构造等很多方面性能卓越;C++的效率高,是底层开发的必备武器

  • C#中的索引器的简单理解和用法

    C#中的类成员可以是任意类型,包括数组和集合。当一个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作

  • 深入C# 序列化(Serialize)、反序列化(Deserialize)

    C#中的序列化和反序列化,序列化是.NET运行时环境用来支持用户定义类型的流化的机制