zoukankan      html  css  js  c++  java
  • 判断一个数是不是2的幂

    

    我们经常会遇到这样一个问题,就是判断某个数据是否为2n次方(1,2,4,8,16...)。例如如果用户输入的不是2^n,则要求用户重新输入。为了说明这种判断算法,我首先构造一个测试程序,代码如下:

    #include <stdio.h>
    
    #include <time.h>
    
     
    
    int main()
    
    {
    
        long unsigned int i;
    
        clock_t start,end;
    
        start = clock();
    
        for(i=1;i<100000000;i++)
    
        {
    
            if(is2Power(i))
    
            {
    
                printf("%ld
    ",i);
    
            }
    
        }
    
        end =clock();
    
        printf("The total time is: %lf",((double)(end-start))/CLOCKS_PER_SEC);
    
        return 0;
    
    }
    

    一般人很容易想到下面的算法:

    int is2Power(long unsigned int num)

    {

        long unsigned int i;

        for(i=1;i<=num;i*=2)

        {

            if(i == num)

            {

                 return 1;

            }

     

        }

        return 0;

    }

    该算法很容易理解,但是效率不算特别高,在我的机器上的测试结果为:The total time is: 28.566000有人提出,其中的i*=2,可以用i<<=1来替换,效率应该会高一些,我们可以尝试一下:

    int is2Power(long unsigned int num)

    {

        long unsigned int i;

        for(i=1;i<=num;i<<=1)

        {

            if(i == num)

            {

                 return 1;

            }

     

        }

        return 0;

    }

    在我的机器上的测试结果为:The total time is: 27.821000,我们发现仅仅提高了不到一秒,基本可以忽略不计。又有人提出,我们可以采取另一种思路,让inum开始每次除2来判断,如果余数不为0立即返回,这样能会快判断出那些不符合条件的值,这样便能加快判断速度。

    int is2Power(long unsigned int num)

    {

        long unsigned int i;

        for(i=num;i>=1;i/=2)

        {

            if(i==1)

                return 1;

            else if(i%2 != 0)

            {

                 return 0;

            }

        }

        return 1;

    }

    这种算法在我的机器上的测试结果为:The total time is: 3.958000,可以看出效率提高了近8倍。这时又有大神提出,由于2n次方的数二进制表示是第1位为1,其余为0,而x-1(假如x2n次方)得到的数的二进制表示恰恰是第1位为0,其余为1,两者相与,得到的结果就为0,否则结果肯定不为0。于是诞生了如下算法:

    int is2Power(long unsigned int num)

    {

        return ((num & (num-1))==0)?1:0;

    }

    简单的有点吓人,而且效率也很高,在我的机器上的测试结果为:The total time is: 1.484000,当然也有一个类似的算法,原理类似:

    int is2Power(long unsigned int num)

    {

        return ((num & (~num+1))==num)?1:0;

    }

    这种算法在我的机器上的测试结果为:The total time is: 1.503000

    很简单的问题,只要我们仔细研究一下还是有不少收获的。

    注:文中的算法仅说明了相对的效率问题,鲁棒性并没有测试,如果你在实际情况中使用,需要注意一下边界值和反常输入情况。

  • 相关阅读:
    进程和线程
    VC中使对话框全屏的方法
    初为项目经理
    Sqlite知识小记
    ERROR L105: PUBLIC REFERS TO IGNORED SEGMENT
    RTX51.LIB NOT FOUND
    Virtual Villagers 攻略
    专业术语常用名词缩写中英文对照
    Eric的四个无刷新(异步更新)示例
    ASP.NET 安全认证(一)—— 如何运用 Form 表单认证 .
  • 原文地址:https://www.cnblogs.com/jiangxinnju/p/5516916.html
Copyright © 2011-2022 走看看