| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3017 人关注过本帖, 3 人收藏
标题:我发一个关于二进制 0 1 相互转换的 帖子 诚征优秀代码 欢迎各路高手进入 ...
只看楼主 加入收藏
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
回复 40楼 beyondyf
i&&i<=x和i<=x&&i还是有少许速度上的差异,在我电脑上同时运行1000万次,前者需要650毫秒,后者需560毫秒,我的代码需1063毫秒,测试代码如下:
程序代码:
#include <stdio.h>
#include <time.h>
unsigned int my(unsigned int x)
{
    unsigned int j,k;
    for(j=1,k=0;x;j<<=1,x>>=1)if(!(x&1))k|=j;;
    return k;
}
unsigned int rev(unsigned int x)
{
    unsigned int i;
    for(i=1;i<=x&&i;i<<=1);
    return x ^ i - 1;
}
unsigned int rev1(unsigned int x)
{
    unsigned int i;
    for(i=1;i&&i<=x;i<<=1);
    return x ^ i - 1;
}

void main()
{
    unsigned int i=345678;
    long t1,t2,t3;
    t1=clock();
    for(i=0;i<10000000;i++)my(3456);    //t1 my
    t1=clock()-t1;
    t2=clock();
    for(i=0;i<10000000;i++)rev1(3456);  //t2 i&&i<=x
    t2=clock()-t2;
    t3=clock();
    for(i=0;i<10000000;i++)rev(3456);   //t3 i<=x&&i
    t3=clock()-t3;
    printf ("my:%d  i&&i<=x:%d  i<=x&&i:%d\n",t1,t2,t3);
}


能编个毛线衣吗?
2015-05-28 07:43
石头star
Rank: 1
等 级:新手上路
帖 子:40
专家分:0
注 册:2015-1-28
收藏
得分:0 
各位版主都学习了多长时间C了?
2015-05-28 15:36
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
两个函数的性能差别只是一条比较指令而已,几个纳秒的时间,放大到1000万倍才能看出90个毫秒的差别,这种优化意义不大,不如交给机器来完成。

如果王姑娘对这点很纠结,那不妨再测试一下这段代码的执行时间。
程序代码:
 unsigned int rev2(register x)

 {
     register i;
     for(i = 1; i <= x && i; i <<= 1);
     return x ^ i - 1;

 }


而且我在我的机器上对比了开优化与不开优化编译王姑娘那段代码,结果很有趣。

正常编译后的执行结果(其实每次执行都不一样,下面只是一个典型结果):(我的机器要比王姑娘的好
my:576  i&&i<=x:386  i<=x&&i:349

开优化(-O)编译后的执行结果
my:245  i&&i<=x:149  i<=x&&i:190

反倒更快了?我们看看这两个函数优化后的汇编代码存在什么差异
程序代码:
_rev:
LFB12:
    .cfi_startproc
    movl    4(%esp), %eax
    testl    %eax, %eax
    je    L10
    movl    $1, %edx
L9:
    addl    %edx, %edx
    cmpl    %edx, %eax
    jb    L8
    testl    %edx, %edx
    jne    L9
    jmp    L8
L10:
    movl    $1, %edx
L8:
    subl    $1, %edx
    xorl    %edx, %eax
    ret
    .cfi_endproc
LFE12:
    .globl    _rev1
    .def    _rev1;    .scl    2;    .type    32;    .endef
_rev1:
LFB13:
    .cfi_startproc
    movl    4(%esp), %eax
    testl    %eax, %eax
    je    L14
    movl    $1, %edx
L13:
    addl    %edx, %edx
    cmpl    %edx, %eax
    jb    L12
    testl    %edx, %edx
    jne    L13
    jmp    L12
L14:
    movl    $1, %edx
L12:
    subl    $1, %edx
    xorl    %edx, %eax
    ret
    .cfi_endproc
LFE13:
    .globl    _rev2
    .def    _rev2;    .scl    2;    .type    32;    .endef

谁看出差别了?反正我是没看出来,完全一样的两段代码。

开始我认为是系统进程切换造成的误差,为了验证这一点我颠倒了两个函数的执行顺序,但结果依旧如此。那位知道原因还请赐教.

重剑无锋,大巧不工
2015-05-28 15:57
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
补充一下我的编译执行环境。gcc 4.8.1,i7-4100MQ的CPU,2.5GHz主频,4G内存,win7 64位系统。

重剑无锋,大巧不工
2015-05-28 16:03
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
回复 43楼 beyondyf

倒不是纠结,只是想验证下运算短路作用大不大。你的算法在大多数情况下是执行了i<=x条件不满足跳出循环的,把它放在前面即可不需要做i!=0的判断,大多数情况下应该执行效率高些。
经你提醒,我也做了些实验,也出现了有趣的结果,比如我把i<=x和i<=x&&i进行比较,发现只判断i<=x需要406,而判断i<=x&&i却只需要375,反复运行多次,这种速度差别很稳定,判断条件复杂些反而执行速度快,特别奇怪。(我现在实验用的台式机典型值为437、422、375)。
我用的是vc6,CPU G2020 2.9G,内存2G,XP,不知道如何优化编译


[ 本帖最后由 wmf2014 于 2015-5-28 17:00 编辑 ]

能编个毛线衣吗?
2015-05-28 16:57
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 45楼 wmf2014
vc6太古老了,建议还是换一个吧。在百度里搜“vc6 开启优化”很容易找到。不由得感慨,现在的学习成本真低啊,至少基础部分是这样的。

重剑无锋,大巧不工
2015-05-28 21:05
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
从数学角度出发  0 1 互换貌似没啥公式吧

DO IT YOURSELF !
2015-05-29 08:41
林月儿
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:138
帖 子:2277
专家分:10647
注 册:2015-3-19
收藏
得分:0 
#include<stdio.h>
#include<conio.h>
int a[80];
void f(int n,int &k){
    int m=n%2;
    n/=2;
    if(n)f(n,k);
    a[k++]=m;
}
main(){
  int i=3456,j=0,ff=0;
  int b[80],k=0;
  f(i,j);
  for(i=0;i<j;i++)printf("%d",a[i]);
  printf("\n");
  for(i=0;i<j;i++){
      if(a[i]==1);
      else ff--;
      if(ff<0)printf("%d",a[i]^1);
  }
  getch();
}

剑栈风樯各苦辛,别时冰雪到时春
2015-05-29 10:33
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 47楼 wp231957
看起来更数学的公式也有,只是实际效率还不如那个循环(事实上那个循环就是根据这一公式改造而来的)。因为对数的计算是通过迭代完成的又是浮点数运算,很耗费时间。

X xor ((2 ^ ([log2(X)] + 1) - 1)

具体如下:由于理论公式的定义域不包含0,所以实际中加了个0.9的补偿因子(不加在多数系统下也可以得到正确结果,但我没有测试过所有的系统,所以还是加上为妙)。另一个0.1是为防止截断误差影响的补偿因子。
程序代码:
 unsigned int rev1(unsigned int x)

 {
     return x ^ (1 << (int)(log(x + 0.9) / log(2) + 0.1) + 1) - 1;

 }

重剑无锋,大巧不工
2015-05-29 11:22
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
回复 49楼 beyondyf
杨兄弟厉害  经过几个测试数据 准确无误

程序代码:
#include <stdio.h>
#include <math.h>

unsigned int rev1(unsigned int x)
{
    return x ^ (1 << (int)(log(x + 0.9) / log(2.0) + 0.1) + 1) - 1;
}

int main()
{    
    printf("%u\n",rev1(3456));
    return 0;
}

DO IT YOURSELF !
2015-06-02 09:02
快速回复:我发一个关于二进制 0 1 相互转换的 帖子 诚征优秀代码 欢迎各路高 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015056 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved