阮建辉的专栏

再NB的肖邦 也弹不出我的愤怒

值交换的两种方法及其效率分析

比如, 我们有两个数a, b要交换值, 我们一般通过这样的方式来达到目的:

int c;

c = a;

a = b;

b = c;

这样来达到交换a, b值的目的;

经常使用位操作的人, 或者会有这样的"高招":

a ^= b;

b ^= a;

a ^= b;

这样也能交换a, b的值, 而且还少用了一个中间参数.

现在我们看到了我们交换值的两种做法,到底哪一种更好呢?

呵呵, 看看反应, 我们将从汇编, 事实(时间)等各个角度来得出结果.

c = b;

mov         eax,dword ptr [ebp-8]

mov         dword ptr [ebp-0Ch],eax

b = a;

mov         ecx,dword ptr [ebp-4]

mov         dword ptr [ebp-8],ecx

a = c;

mov         edx,dword ptr [ebp-0Ch]

mov         dword ptr [ebp-4],edx

总共有六条汇编指令;

我们再看看后一种方法的汇编指令条数:

a ^= b;

mov         eax,dword ptr [ebp-4]

xor         eax,dword ptr [ebp-8]

mov         dword ptr [ebp-4],eax

b ^= a;

mov         ecx,dword ptr [ebp-8]

xor         ecx,dword ptr [ebp-4]

mov         dword ptr [ebp-8],ecx

a ^= b;

mov         edx,dword ptr [ebp-4]

xor         edx,dword ptr [ebp-8]

mov         dword ptr [ebp-4],edx

怎么样? 后一种方法足足比前一种方法多了三条指令. 当然, 更直观的方法还是来点测试, 我们可以更显而易见的看到对比的结果, 而且这个结果也反映了一个比较普遍的策略.

第一种方法:

    int a = 9;<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    int b = 8;

    int c;

   

    int nCount;

    nCount = GetTickCount();

    printf("Start time: %d/n", nCount);

    for (int i = 0; i < 100000000; i++)

    {

        c = a;

        a = b;

        b = c;

    }

    nCount = GetTickCount();

    printf("End   time: %d/n", nCount);

结果是:

Start time: 38830024

End   time: 38830395

用了371 ms.

 

第二种方法:

    int a = 9;

    int b = 8;

 

    int nCount;

    nCount = GetTickCount();

    printf("Start time: %d/n", nCount);

    for (int i = 0; i < 100000000; i++)

    {

        a ^= b;

        b ^= a;

        a ^= b;

    }

    nCount = GetTickCount();

    printf("End   time: %d/n", nCount);

结果是:

Start time: 38955024

End   time: 38956125

用了1001ms.

两者的结果在大量重复操作下都呈现数量级上的差距了.

从这两种方法我们可以看出, 虽然第一种方法时间少, 但是其增加了一个变量的消耗, 第二种方法虽然时间多, 但是节省了一个变量的空间, 但是其损失的时间效率确是很客观的.

在某些场合, 时间很重要, 而存储器容量显然还没有到捉襟见肘的时候, 第一种方法显然是合适的, 它其实就是一个空间换时间的策略体现, 而且它更容易理解; 而第二种在理解上就比较不那么容易(你也许应该自己做一下逻辑运算才能知道它们确实交换了值:), 而且其时间损失是显而易见的(在电量比较极其的设备中, 这也是不能容忍的). 这也是第二中方法几乎快销声匿迹的原因了. 有一次在某论坛里看到有人拿出了第二种方法的代码, 还说是绝妙的三行代码, 呵呵.

 

阅读更多
文章标签: 汇编 c 测试 存储
个人分类: 技术
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭