有两个比较两个值大小的函数,看哪个更快?

时间:2020-12-27 19:14:44
下面两个都是内联函数一个很常见,一个不怎么常见连比较操作有关的都没用到。
inline int min( int a, int b)
{
    return a>b?b:a;
}

inline int min( int a, int b)
{
    int mask = (a - b) >> 31;
    return (a & mask) | (b & ~mask);
}

44 个解决方案

#1


应该一样,就算有区别也看不出来


细说的话第一个快

一个 > 应该比 - 快吧

#2


还是用上面那个吧,底下那个,鬼知道在移植时会出什么问题

#3


第二个函数中 mask表示a,b的大小情况,a>b则mask=0,返回的就是b;a<b则mask=1,返回的就是a的值; 

#4


速度还是差别不大吧,不过很简单的比较没必要用那么复杂的方法吧

#5


下面一种
a-b时是不是有可能越界呀???!!!

#6


int max(int x,int y) 

//没有新变量,没有比较,没有判断语句 看好了哦 
return (a+b+abs(a-b))/2; 

#7


int max(int x,int y) 

int buf[2]={x,y}; 
int z; 

z=x-y; 
z = ((unsigned int &)z)>>31;    
return buf[z]; 

#8


#include "stdio.h" 

int max(int x,int y) 

   int buf[2]={x,y}; 
   unsigned int z; 
   z=x-y; 
   z = z>>31;      
   return buf[z]; 

int main( ) 

  int ma; 
  ma=max(2,-1); 
  printf("max=%d\n",ma); 
  return 0; 
}

#9


移位再与完全没必要。
现在的CPU指令集提供了大小比较的指令,硬件也支持快速比较两个数大小。
当然比第二个快了。

#10


inline int min( int a, int b)
{
    int mask = (a - b) >> 31;
    return (a & mask) | (b & ~mask);
}

min = (a.b + c.!b)(“.”代表与,“!”代表非,“+”代表或)

就属这个牛了,不过函数名如果起得不当,非让其他人抓狂

#11


如果判断溢出或者用6楼的办法那根本不要比较哪个更快了,9楼硬件直接比较也存在时间差的。

#12


直觉第一个快

#13


第一个快,再就是7楼那个很经典,不容易想到

#14


一般来说,简单的比复杂的快
等我看下glibc怎么写的

#15


直接用if...return...else...return...更快。

#16


引用 6 楼 lovesi3344 的回复:
int max(int x,int y)
{
//没有新变量,没有比较,没有判断语句 看好了哦
return (a+b+abs(a-b))/2;

}

自己看看max(0x7fffffff,-0x7fffffff)输出什么东西。用减法的必挂。

#17


thanks for your help

#18


6l,呵呵,参量名错了

#19


没测试过 感觉第二个快 没有if语句 

#20


第2个可读性不是很好
速度应该差不多

#21


感觉第一个快,cmp就是先做减法再查看标志位的。
第二个int mask = (a - b) >> 31;都已经做了减法了,还能快到哪去啊?

#22


VC6调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。

#23


a-b会溢出的

#24


引用 23 楼 arthurjava 的回复:
a-b会溢出的

要的就是溢出

#25


引用 24 楼 fo1_sky 的回复:
引用 23 楼 arthurjava 的回复:
a-b会溢出的

要的就是溢出

a-b的溢出是与31这个数字相关的,在其他平台上不一定可以确切运行

#26


溢出的值不是不定的么??
那不是和平台还有编译器有关系??
那就有可能出现意外了??

#27


一看就是第一个快

#28


看编译器有没有优化了
一般来说,还是第一个快

#29


嗯,其实我觉得,循环上1w次,看看哪个需要时间少,哪个就快,用事实来检验吧.

#30


让编译器来为我们解答!
第一个的汇编代码:
00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  8B550C            mov edx,[ebp+0xc]
00000006  8B4508            mov eax,[ebp+0x8]
00000009  39D0              cmp eax,edx
0000000B  7E02              jng 0xf
0000000D  89D0              mov eax,edx
0000000F  5D                pop ebp
00000010  C3                ret

第二个的汇编代码:
00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  83EC10            sub esp,byte +0x10
00000006  8B450C            mov eax,[ebp+0xc]
00000009  8B5508            mov edx,[ebp+0x8]
0000000C  89D1              mov ecx,edx
0000000E  29C1              sub ecx,eax
00000010  89C8              mov eax,ecx
00000012  C1F81F            sar eax,0x1f
00000015  8945FC            mov [ebp-0x4],eax
00000018  8B45FC            mov eax,[ebp-0x4]
0000001B  8B5508            mov edx,[ebp+0x8]
0000001E  21C2              and edx,eax
00000020  8B45FC            mov eax,[ebp-0x4]
00000023  F7D0              not eax
00000025  23450C            and eax,[ebp+0xc]
00000028  09D0              or eax,edx
0000002A  C9                leave
0000002B  C3                ret

我是Linux下gcc 4.4.1
我想从代码的复杂度来看很容易看出哪个的效率高。第二个是明显的舍近求远。
让我们继续做一个实验,执行两段代码一万次,看哪个的耗时少。
下面是测试程序:
#include <sys/time.h>
#include <stdio.h>
int min1(int a,int b)
{
return a>b?b:a;
}
int min2(int a,int b)
{

    int mask = (a - b) >> 31;
    return (a & mask) | (b & ~mask); 
}
int main()
{
struct timeval t,end;
gettimeofday(&t,NULL);
int i=0;
while(i++<10000){
min1(1,2);
}
gettimeofday(&end,NULL);
printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);

gettimeofday(&t,NULL);
i=0;
while(i++<10000){
min2(1,2);
}
gettimeofday(&end,NULL);
printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);

return 0;
}

我获得的输出是:
0.000000sec,177.000000usec
0.000000sec,256.000000usec
很明显,简单的那个快

#31


引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:
Assembly code0000000055push ebp00000001  89E5mov ebp,esp00000003  8B550Cmov edx,[ebp+0xc]00000006  8B4508mov eax,[ebp+0x8]
00000009  39D0cmp eax,edx
0000000B  7E02jng0xf
0000000D  89D0mov eax,edx
0000000F  5Dpop ebp00000010  C3ret
第二个的汇编代码:
Assembly code0000000055push ebp00000001  89E5mov ebp,esp00000003  83EC10sub esp,byte +0x1000000006  8B450Cmov eax,[ebp+0xc]
00000009  8B5508mov edx,[ebp+0x8]
0000000C  89D1mov ecx,edx
0000000E  29C1sub ecx,eax00000010  89C8mov eax,ecx00000012  C1F81Fsar eax,0x1f00000015  8945FCmov [ebp-0x4],eax
00000018  8B45FCmov eax,[ebp-0x4]
0000001B  8B5508mov edx,[ebp+0x8]
0000001E  21C2and edx,eax00000020  8B45FCmov eax,[ebp-0x4]00000023  F7D0not eax00000025  23450Cand eax,[ebp+0xc]
00000028  09D0or eax,edx
0000002A  C9leave
0000002B  C3ret
我是Linux下gcc 4.4.1
我想从代码的复杂度来看很容易看出哪个的效率高。第二个是明显的舍近求远。
让我们继续做一个实验,执行两段代码一万次,看哪个的耗时少。
下面是测试程序:
C/C++ code#include<sys/time.h>
#include<stdio.h>int min1(int a,int b)
{return a>b?b:a;
}int min2(int a,int b)
{int mask= (a- b)>>31;return (a& mask)| (b&~mask); 
}int main()
{struct timeval t,end;
    gettimeofday(&t,NULL);int i=0;while(i++<10000){
        min1(1,2);
    }
    gettimeofday(&end,NULL);
    printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);

    gettimeofday(&t,NULL);
    i=0;while(i++<10000){
        min2(1,2);
    }
    gettimeofday(&end,NULL);
    printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);return0;
}
我获得的输出是:
0.000000sec,177.000000usec
0.000000sec,256.000000usec
很明显,简单的那个快


牛B!!!!

#32


进来学习一下 看来自己要学的东西很多

#33


学习了,谢谢...

#34


30楼,- -!牛B!!!

#35


顶30楼,我喜欢

#36


减法不太可取,以下程序中输出相反:
inline int min( int a, int b)
{
int mask = (a - b) >> 31;
return (a & mask) | (b & ~mask);
}
int main(void)
{
int i = -1500000000;
int j = 1500000000;
printf("min=%d", min(i, j));
return 0;
}


希望楼主仔细了解一下:
sub eax,ebx
jl _@1
jb _@2
有什么区别

#37


学习 学习!

#38


不同环境下 int 不一定会是4位。
所以用>>31,这种不是很好。

#39


引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:

Assembly code
00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  8B550C            mov edx,[ebp+0xc]
00000006  8B4508            mov e……

支持!
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

#40


个人更喜欢第一种。

#41


太牛叉了,这么简单的事情都考虑这么多办法,不过话说钻牛角尖也不太好吧?

#42


引用 31 楼 bluestar2009 的回复:
引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:
Assembly code0000000055push ebp00000001 89E5mov ebp,esp00000003 8B550Cmov edx,[ebp+0xc]00000006 8B4508mov eax,[ebp+0x8]
00000009 39D0cmp eax,edx
0000000B……
牛牛B!

#43


没什么区别

#44


引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:

Assembly code

00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  8B550C            mov edx,[ebp+0xc]
00000006  8B4508            mov……

这不就妥了

#1


应该一样,就算有区别也看不出来


细说的话第一个快

一个 > 应该比 - 快吧

#2


还是用上面那个吧,底下那个,鬼知道在移植时会出什么问题

#3


第二个函数中 mask表示a,b的大小情况,a>b则mask=0,返回的就是b;a<b则mask=1,返回的就是a的值; 

#4


速度还是差别不大吧,不过很简单的比较没必要用那么复杂的方法吧

#5


下面一种
a-b时是不是有可能越界呀???!!!

#6


int max(int x,int y) 

//没有新变量,没有比较,没有判断语句 看好了哦 
return (a+b+abs(a-b))/2; 

#7


int max(int x,int y) 

int buf[2]={x,y}; 
int z; 

z=x-y; 
z = ((unsigned int &)z)>>31;    
return buf[z]; 

#8


#include "stdio.h" 

int max(int x,int y) 

   int buf[2]={x,y}; 
   unsigned int z; 
   z=x-y; 
   z = z>>31;      
   return buf[z]; 

int main( ) 

  int ma; 
  ma=max(2,-1); 
  printf("max=%d\n",ma); 
  return 0; 
}

#9


移位再与完全没必要。
现在的CPU指令集提供了大小比较的指令,硬件也支持快速比较两个数大小。
当然比第二个快了。

#10


inline int min( int a, int b)
{
    int mask = (a - b) >> 31;
    return (a & mask) | (b & ~mask);
}

min = (a.b + c.!b)(“.”代表与,“!”代表非,“+”代表或)

就属这个牛了,不过函数名如果起得不当,非让其他人抓狂

#11


如果判断溢出或者用6楼的办法那根本不要比较哪个更快了,9楼硬件直接比较也存在时间差的。

#12


直觉第一个快

#13


第一个快,再就是7楼那个很经典,不容易想到

#14


一般来说,简单的比复杂的快
等我看下glibc怎么写的

#15


直接用if...return...else...return...更快。

#16


引用 6 楼 lovesi3344 的回复:
int max(int x,int y)
{
//没有新变量,没有比较,没有判断语句 看好了哦
return (a+b+abs(a-b))/2;

}

自己看看max(0x7fffffff,-0x7fffffff)输出什么东西。用减法的必挂。

#17


thanks for your help

#18


6l,呵呵,参量名错了

#19


没测试过 感觉第二个快 没有if语句 

#20


第2个可读性不是很好
速度应该差不多

#21


感觉第一个快,cmp就是先做减法再查看标志位的。
第二个int mask = (a - b) >> 31;都已经做了减法了,还能快到哪去啊?

#22


VC6调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。

#23


a-b会溢出的

#24


引用 23 楼 arthurjava 的回复:
a-b会溢出的

要的就是溢出

#25


引用 24 楼 fo1_sky 的回复:
引用 23 楼 arthurjava 的回复:
a-b会溢出的

要的就是溢出

a-b的溢出是与31这个数字相关的,在其他平台上不一定可以确切运行

#26


溢出的值不是不定的么??
那不是和平台还有编译器有关系??
那就有可能出现意外了??

#27


一看就是第一个快

#28


看编译器有没有优化了
一般来说,还是第一个快

#29


嗯,其实我觉得,循环上1w次,看看哪个需要时间少,哪个就快,用事实来检验吧.

#30


让编译器来为我们解答!
第一个的汇编代码:
00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  8B550C            mov edx,[ebp+0xc]
00000006  8B4508            mov eax,[ebp+0x8]
00000009  39D0              cmp eax,edx
0000000B  7E02              jng 0xf
0000000D  89D0              mov eax,edx
0000000F  5D                pop ebp
00000010  C3                ret

第二个的汇编代码:
00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  83EC10            sub esp,byte +0x10
00000006  8B450C            mov eax,[ebp+0xc]
00000009  8B5508            mov edx,[ebp+0x8]
0000000C  89D1              mov ecx,edx
0000000E  29C1              sub ecx,eax
00000010  89C8              mov eax,ecx
00000012  C1F81F            sar eax,0x1f
00000015  8945FC            mov [ebp-0x4],eax
00000018  8B45FC            mov eax,[ebp-0x4]
0000001B  8B5508            mov edx,[ebp+0x8]
0000001E  21C2              and edx,eax
00000020  8B45FC            mov eax,[ebp-0x4]
00000023  F7D0              not eax
00000025  23450C            and eax,[ebp+0xc]
00000028  09D0              or eax,edx
0000002A  C9                leave
0000002B  C3                ret

我是Linux下gcc 4.4.1
我想从代码的复杂度来看很容易看出哪个的效率高。第二个是明显的舍近求远。
让我们继续做一个实验,执行两段代码一万次,看哪个的耗时少。
下面是测试程序:
#include <sys/time.h>
#include <stdio.h>
int min1(int a,int b)
{
return a>b?b:a;
}
int min2(int a,int b)
{

    int mask = (a - b) >> 31;
    return (a & mask) | (b & ~mask); 
}
int main()
{
struct timeval t,end;
gettimeofday(&t,NULL);
int i=0;
while(i++<10000){
min1(1,2);
}
gettimeofday(&end,NULL);
printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);

gettimeofday(&t,NULL);
i=0;
while(i++<10000){
min2(1,2);
}
gettimeofday(&end,NULL);
printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);

return 0;
}

我获得的输出是:
0.000000sec,177.000000usec
0.000000sec,256.000000usec
很明显,简单的那个快

#31


引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:
Assembly code0000000055push ebp00000001  89E5mov ebp,esp00000003  8B550Cmov edx,[ebp+0xc]00000006  8B4508mov eax,[ebp+0x8]
00000009  39D0cmp eax,edx
0000000B  7E02jng0xf
0000000D  89D0mov eax,edx
0000000F  5Dpop ebp00000010  C3ret
第二个的汇编代码:
Assembly code0000000055push ebp00000001  89E5mov ebp,esp00000003  83EC10sub esp,byte +0x1000000006  8B450Cmov eax,[ebp+0xc]
00000009  8B5508mov edx,[ebp+0x8]
0000000C  89D1mov ecx,edx
0000000E  29C1sub ecx,eax00000010  89C8mov eax,ecx00000012  C1F81Fsar eax,0x1f00000015  8945FCmov [ebp-0x4],eax
00000018  8B45FCmov eax,[ebp-0x4]
0000001B  8B5508mov edx,[ebp+0x8]
0000001E  21C2and edx,eax00000020  8B45FCmov eax,[ebp-0x4]00000023  F7D0not eax00000025  23450Cand eax,[ebp+0xc]
00000028  09D0or eax,edx
0000002A  C9leave
0000002B  C3ret
我是Linux下gcc 4.4.1
我想从代码的复杂度来看很容易看出哪个的效率高。第二个是明显的舍近求远。
让我们继续做一个实验,执行两段代码一万次,看哪个的耗时少。
下面是测试程序:
C/C++ code#include<sys/time.h>
#include<stdio.h>int min1(int a,int b)
{return a>b?b:a;
}int min2(int a,int b)
{int mask= (a- b)>>31;return (a& mask)| (b&~mask); 
}int main()
{struct timeval t,end;
    gettimeofday(&t,NULL);int i=0;while(i++<10000){
        min1(1,2);
    }
    gettimeofday(&end,NULL);
    printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);

    gettimeofday(&t,NULL);
    i=0;while(i++<10000){
        min2(1,2);
    }
    gettimeofday(&end,NULL);
    printf("%lfsec,%lfusec\n",(double)end.tv_sec-t.tv_sec,(double)end.tv_usec-t.tv_usec);return0;
}
我获得的输出是:
0.000000sec,177.000000usec
0.000000sec,256.000000usec
很明显,简单的那个快


牛B!!!!

#32


进来学习一下 看来自己要学的东西很多

#33


学习了,谢谢...

#34


30楼,- -!牛B!!!

#35


顶30楼,我喜欢

#36


减法不太可取,以下程序中输出相反:
inline int min( int a, int b)
{
int mask = (a - b) >> 31;
return (a & mask) | (b & ~mask);
}
int main(void)
{
int i = -1500000000;
int j = 1500000000;
printf("min=%d", min(i, j));
return 0;
}


希望楼主仔细了解一下:
sub eax,ebx
jl _@1
jb _@2
有什么区别

#37


学习 学习!

#38


不同环境下 int 不一定会是4位。
所以用>>31,这种不是很好。

#39


引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:

Assembly code
00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  8B550C            mov edx,[ebp+0xc]
00000006  8B4508            mov e……

支持!
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。

#40


个人更喜欢第一种。

#41


太牛叉了,这么简单的事情都考虑这么多办法,不过话说钻牛角尖也不太好吧?

#42


引用 31 楼 bluestar2009 的回复:
引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:
Assembly code0000000055push ebp00000001 89E5mov ebp,esp00000003 8B550Cmov edx,[ebp+0xc]00000006 8B4508mov eax,[ebp+0x8]
00000009 39D0cmp eax,edx
0000000B……
牛牛B!

#43


没什么区别

#44


引用 30 楼 yzx714 的回复:
让编译器来为我们解答!
第一个的汇编代码:

Assembly code

00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  8B550C            mov edx,[ebp+0xc]
00000006  8B4508            mov……

这不就妥了