反转一个字节

很久以前发过一个相关的随笔:

 反转一个字节的算法
以及相关的效率探讨:

效率的边界--几种反转字节算法分析

昨天 周星星 旧事重提,又引发了对这个简单问题的讨论,相关的东西以前已经讨论了很多了,这里不再重复,只提供两个新的算法:

首先是周星星的新算法:

unsigned  char  reverse8( unsigned  char  c )
{
    c 
=  ( c  &   0x55  )  <<   1   |  ( c  &   0xAA  )  >>   1 ;
    c 
=  ( c  &   0x33  )  <<   2   |  ( c  &   0xCC  )  >>   2 ;
    c 
=  ( c  &   0x0F  )  <<   4   |  ( c  &   0xF0  )  >>   4 ;
    
return  c;
}


经过测试,这是目前在32位环境,除查表法之外的最高效算法。

我也尝试了一下,要超越这个算法的效率的确很难,几经周折也没有能够成功。不过这个过程中,考虑了另外一个算法,需要64位环境的支持,代码如下:

typedef unsigned  long   U_INT64; 
// 64位环境。long应该是64bit长度。
// 如果有更适合的类型,替换这个typedef即可。
typedef unsigned  char  U_INT8;
U_INT8 reverse64( U_INT8 C )
{
    U_INT64 c 
=  C;
    U_INT64 a 
=   0xF7B3D591E6A2C480 ;
    U_INT8 result 
=  ( ( a  >>  ( (c  &   0x0F <<   2  ) )  <<   4  )
        
|  ( ( a  >>  ( (c  &   0xF0 >>   2  ) )  &   0x0F  );
    
return  result;
}


这个算法的本质还是查表法,但是利用64bit变量代替了表,利用移位代替了查表过程中的寻址。
理论上这个算法应该有更高的效率,尽管仍然无法超越原始的查表法。

但是因为我没有64位的编译环境和运行环境,所以在此恳请有条件的朋友帮忙测试一下这两个代码在64位环境下的表现,参考的测试代码如下:

typedef unsigned  long   U_INT64;
typedef unsigned 
char  U_INT8;
U_INT8 reverse64( U_INT8 C )
{
    U_INT64 c 
=  C;
    U_INT64 a 
=   0xF7B3D591E6A2C480 ;
    U_INT8 result 
=  ( ( a  >>  ( (c  &   0x0F <<   2  ) )  <<   4  )
        
|  ( ( a  >>  ( (c  &   0xF0 >>   2  ) )  &   0x0F  );
    
return  result;
}


U_INT8 reverse8( U_INT8 c )
{
    c 
=  ( c  &   0x55  )  <<   1   |  ( c  &   0xAA  )  >>   1 ;
    c 
=  ( c  &   0x33  )  <<   2   |  ( c  &   0xCC  )  >>   2 ;
    c 
=  ( c  &   0x0F  )  <<   4   |  ( c  &   0xF0  )  >>   4 ;
    
return  c;
}


// 效率测试代码:
#include  < iostream >
using   namespace  std;
inline U_INT64 GetCycleCount()
{
        __asm RDTSC 
// 获取CPU时间戳
}


int  main( int  argc,  char *  argv[])
{
        U_INT64 i 
=   0 ,n  =   10000 ;
        U_INT8 c 
=   0 ;

        U_INT64 t1 
=  GetCycleCount();
       
        
for ( i  =   0 ; i  <  n; i ++ )
                c 
+=  reverse64(i);

        U_INT64 t2 
=  GetCycleCount();

        
for ( i  =   0 ; i  <  n; i ++ )
                c 
+=  reverse8(i);

        U_INT64 t3 
=  GetCycleCount();

        cout 
<<   "  T1 =  "   <<  U_INT64((t2 - t1) / n)
                
<<   "  T2 =  "   <<  U_INT64((t3 - t2) / n)
                
<<   "    C =  "   <<  c          // 输出c是为了避免编译器优化。
                 <<  endl;

        
return   0 ;
}


由于对64位环境近乎无知,所以代码可能无法直接编译运行,仅供参考。
谢谢合作:)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值