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

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

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

  • 相关阅读:
    【转载】Sqlserver存储过程中使用Select和Set给变量赋值
    【转载】腾讯云如何将一个域名解析到另一个域名上
    【转载】Sqlserver限制最大可使用内存
    【转载】 腾讯云通过设置安全组禁止某些IP访问你的服务器
    【转载】 C#使用Select方法快速获取List集合集合中某个属性的所有值集合
    【转载】哪些域名后缀可在工信部进行备案操作
    【转载】 C#使用string.Join快速用特定字符串串联起数组
    【转载】Sqlserver使用Convert函数进行数据类型转换
    【转载】Sqlserver根据生日计算年龄
    【转载】 腾讯云硬盘不够用,如何对硬盘进行扩容
  • 原文地址:https://www.cnblogs.com/jiangxinnju/p/5516916.html
Copyright © 2011-2022 走看看