VB.NET位运算之交换两个数字的效率分析

2 篇文章 0 订阅
1 篇文章 0 订阅

一、问题描述

近日,同事Kings给我看了一段奇怪的C#代码,鄙人对位运算了解甚少,初看之下懵了,还真不知道其功能,代码如下:

Int32 a=10,b=20;
a=a^b;
b=a^b;
a=a^b;
不过,我相信各位看客肯定都遇到过类似代码,对了,就是不用中间变量完成交换两个数字的功能。

出于个人喜好,我习惯性的想到:那么这种通过位运算的方式进行数字交换的效率和普通交换方式的效率相比,孰高孰低呢?

还是测试。

二、问题剖析

先用C#语言来测试,代码如下:

private void ExchangeMethodTest()
{
    Int32 a = 10, b = 20;
    Console.WriteLine(op_format, "Cycles", count);

    Stopwatch sw = Stopwatch.StartNew();
    for (Int32 i = 0; i < count; i++)
    {
        Int32 temp = 0;
        temp = b;
        b = a;
        a = temp;
    }
    Console.WriteLine(op_format, "Common Exchange Method", sw.Elapsed);

    for (Int32 i = 0; i < count; i++)
    {
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
    }
    Console.WriteLine(op_format, "Use Bit Exchange Method", sw.Elapsed);
}
测试结果截图如下:

ExchangeMethodTest_1

ExchangeMethodTest_2

哎,C#位运算的效率怎么会这么低呐?

再看看VB的,不过我想效率应该也不怎么样,测试一下再说吧,代码如下:

Private Sub ExchangeMethodTest()
    Dim intA As Int32 = 10, intB As Int32 = 20
    Dim sw As Stopwatch = Stopwatch.StartNew()
    For i As Int32 = 0 To count
        Dim j As Int32
        j = intB
        intB = intA
        intA = j
    Next
    Console.WriteLine(op_format, "Common Exchange Method", sw.Elapsed)

    sw = Stopwatch.StartNew()
    For i As Int32 = 0 To count
        intA = intA Xor intB
        intB = intA Xor intB
        intA = intA Xor intB
    Next
    Console.WriteLine(op_format, "Use Bit Exchange Method", sw.Elapsed)
End Sub
运行结果如下截图:

ExchangeMethodTest_3

ExchangeMethodTest_4

哦?VB中位运算的效率是还高于C#的!

但是不论是C#还是VB,在位运算的效率都要低于普通的交换方法。看来,这种位运算不仅难懂,而且效率不高(这里仅只.net平台的C#和VB)。

反汇编(以VB为例)显示结果无法复制文本,只好截图了:

一下是IL代码:

.method private static void ExchangeMethodTest() cil managed
{
    .maxstack 3
    .locals init (
        [0] int32 intA,
        [1] int32 intB,
        [2] class [System]System.Diagnostics.Stopwatch sw,
        [3] int32 i,
        [4] int32 j,
        [5] int32 V_5,
        [6] int32 VB$CG$t_i4$S0)
    L_0000: nop 
    L_0001: ldc.i4.s 10
    L_0003: stloc.0 
    L_0004: ldc.i4.s 20
    L_0006: stloc.1 
    L_0007: ldstr "{0,-27}:{1}"
    L_000c: ldstr "Cycles"
    L_0011: ldc.i4 0x3b9aca00
    L_0016: box int32
    L_001b: call void [mscorlib]System.Console::WriteLine(string, object, object)
    L_0020: nop 
    L_0021: call class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
    L_0026: stloc.2 
    L_0027: ldc.i4.0 
    L_0028: stloc.3 
    L_0029: ldloc.1 
    L_002a: stloc.s j
    L_002c: ldloc.0 
    L_002d: stloc.1 
    L_002e: ldloc.s j
    L_0030: stloc.0 
    L_0031: nop 
    L_0032: ldloc.3 
    L_0033: ldc.i4.1 
    L_0034: add.ovf 
    L_0035: stloc.3 
    L_0036: ldloc.3 
    L_0037: ldc.i4 0x3b9aca00
    L_003c: stloc.s VB$CG$t_i4$S0
    L_003e: ldloc.s VB$CG$t_i4$S0
    L_0040: ble.s L_0029
    L_0042: ldstr "{0,-27}:{1}"
    L_0047: ldstr "Common Exchange Method"
    L_004c: ldloc.2 
    L_004d: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
    L_0052: box [mscorlib]System.TimeSpan
    L_0057: call void [mscorlib]System.Console::WriteLine(string, object, object)
    L_005c: nop 
    L_005d: call class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
    L_0062: stloc.2 
    L_0063: ldc.i4.0 
    L_0064: stloc.s V_5
    L_0066: ldloc.0 
    L_0067: ldloc.1 
    L_0068: xor       <---异或操作
    L_0069: stloc.0 
    L_006a: ldloc.0 
    L_006b: ldloc.1 
    L_006c: xor       <---异或操作
    L_006d: stloc.1 
    L_006e: ldloc.0 
    L_006f: ldloc.1 
    L_0070: xor       <---异或操作
    L_0071: stloc.0 
    L_0072: nop 
    L_0073: ldloc.s V_5
    L_0075: ldc.i4.1 
    L_0076: add.ovf 
    L_0077: stloc.s V_5
    L_0079: ldloc.s V_5
    L_007b: ldc.i4 0x3b9aca00
    L_0080: stloc.s VB$CG$t_i4$S0
    L_0082: ldloc.s VB$CG$t_i4$S0
    L_0084: ble.s L_0066
    L_0086: ldstr "{0,-27}:{1}"
    L_008b: ldstr "Use Bit Exchange Method"
    L_0090: ldloc.2 
    L_0091: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
    L_0096: box [mscorlib]System.TimeSpan
    L_009b: call void [mscorlib]System.Console::WriteLine(string, object, object)
    L_00a0: nop 
    L_00a1: nop 
    L_00a2: ret 
}
三、总结

综上所述,交换两个数字还是使用中间变量吧。

另外,截图中的反汇编和IL代码还望有高手指点一二!

不知C/C++在位运算交换两个数字时的效率如何,还望高手指点一二!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值