一道面试题的实验

    昨天中午在《程序员》杂志上看到一道面试题,题目是这样的:

   “怎样知道一个数是不是2的N次方,怎样判断一个数是奇数还是偶数”

    后面一个好回答,前面的思考了一分钟也有答案了,然后发给同事看。一个同事说这后面的太简单了,直接对2取余就知道了。我对他说当你认为很容易的时候得考虑方案的效率。 第一眼接触这种题就知道是考“位运算”,后面的使用 “X & 1==0” 来判断是否为奇偶.同事问我这种办法能提高多少效率,我说在JAVA平台上应该感觉不到,但在C/C++语言里可是两个数量级。我是这么说,也是根据理论来讲的,没试验过,刚好试验一下结果。于是很快写了一个JAVA的测试程序如下:

 

 

import java.util.Date;

class Test
{
    
public static void main(String[] args)
    {
        
        Date a
=new Date(),b;
        
for(int i=0;i<2000000000;i++){
            
if(i%2==0){};
        }
        b
=new Date();
        System.out.println(b.getTime()
-a.getTime());
        b
=new Date();
        
for(int i=0;i<2000000000;i++){
            
if((i&1)==0){};
        }
        a
=new Date();
        System.out.println(a.getTime()
-b.getTime());
    }
}

 

测试平台是CPU:P8400 2.26GHz ,2G DDR3内存运行上面代码得出结果都在6秒之上,两者相差不大,有时位运算所花的时间甚至比取余还多。

为了验证在C语言下的情况,特地下了一个Turbo C 2.0的编译器,程序代码如下

 

 

#include <stdio.h>
#include 
<dos.h>

main(){
  
long i;
  
struct time st,et;
  gettime(
&st);
  
for(i=0;i<100000000L;i++){
    
if(i%2==0){;}
  }
  gettime(
&et);


  printf(
"%d\n",(et.ti_min-st.ti_min) * 60 * 100+(et.ti_sec-st.ti_sec)*100+et.ti_hund-st.ti_hund);
  gettime(
&st);
  
for(i=0;i<200000000L;i++){
    
if(i&1==0){;}
  }
  gettime(
&et);
  printf(
"%d",(et.ti_min-st.ti_min) * 60 * 100+(et.ti_sec-st.ti_sec)*100+et.ti_hund-st.ti_hund);

}

 

这段代码运行次数有点不同,取余运算1亿次,位运算运算2亿次,原因是取余实在太慢了,等不及。结果是取余基本在27秒左右,而位运算保持在0.7秒左右看来真如预料,C语言中的位运算和取余完全不在一个数量级上.但让人不解的是,为啥C语言的取余居然没有JAVA这种中间语言快呢.

 

晚上回到家,又用家里的台式机试验了一下.家里的运行环境是:CPU E5200 2.5GHz 内存 2G DDR2 800MHz

JAVA代码相同,运行几次后这回有差距了, 取余运算一直在5秒以上,而位运算一直是1秒多一点. 难道和CPU的运算指令有关? 末了也测试了一下在C环境下的情况,这回用的是VC 6.0环境,使用C++语言,代码如下

 



#include 
<iostream>
#include 
<ctime>
using namespace std;

int main(){
     clock_t s;
     
     unsigned 
int i,max=2E8;
     s
=clock();
     cout
<<max<<endl;
     
for(i=1;i<max;i++)
     {
if(i%2==0){;}}

     cout
<<(clock()-s)<<endl;

     s
=clock();
     
for(i=1;i<max;i++)
     {
if(i&1==0){;}}

     cout
<<(clock()-s)<<endl;

     
return 0;
}

 

使用DEBUG模式,因为使用Release模式结果总是0即使把循环次数剩以10,还是如此(可见VC的效率了)。

这样运算的结果相差不多,都是在0.3-0.4秒之间,这样看不出差别,基本这此时间都是浪费在循环上了,里面的运算没有耗费多少时间,因为我尝试将里面的语句注释掉,运行的时间差别不大。

 

总结:

    其实没啥好总结的,比如C语言的取余为啥比JAVA还慢,不得而知。我感觉可能JAVA中的算法加强了或者编译器有优化,毕竟TURBOC 编译器出年好多年了。

   

 

另外篇头的面试题,前面的问题“如何知道一个数是不是2的N次方” 答案是 X<<1 看是否为0

posted @ 2009-06-04 17:10  taia  阅读(2744)  评论(19编辑  收藏  举报