C# 中如何检查无符号长整形数是否为2的正整次方[终极版]

本文探讨了判断一个数是否为2的正整数次方的算法,并逐步优化算法效率。从简单的除2法开始,经过奇偶判定优化,最终通过二进制位操作达到极致效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚接触这个命题的时候,简单地想了想——很简单:
第一个方案:除2法。将它一直除以2,最后得到1则标识这个数是2的正整次方,得到一个小于1的小数则不是。

后来一想,这样的算法效率肯定不敢恭维,于是就有了下面的初步改进版:除2法的基础上进行奇偶判定。

private static bool IsPowerOfTwo_Obsolete(ulong value)
{
    double tmp = 0;
    while (value > 2)
    {
        /* 
         * 若 value 的值是2的正整数次方,则一直除以2的操作得到的数,必定仍然为偶数,直到为 1。
         * 反之,若 value 的值不是2的正整数次方,则除以2的操作必定在某一步的时候会产生一个奇数,假定这个奇数是N
         * 此时 N 除以2得到的浮点数必定和 N 除以2得到的整数值不相等。
         */ 
        tmp = Convert.ToDouble(value) / 2;
        if (tmp % 2 != 0)
        {
            return false;
        }
        else {
            value = value / 2;
        }
    }

    return value == 2;
}

其实写到这里,这个方法已经不错了。但后来继续挖掘信息,又一次改进了方法:进行二进制位比较,效率得到了大幅的提高:

//检查是否为2的正整数次方
private static bool IsPowerOfTwo_Obsolete2(ulong value)
{
    if (value > 1)
    {
        /* 
         * 针对每一个 ulong 的正整数,如果是2的正整数次方,则转换为二进制表示时一定有且仅有一个“1”存在。
         * 基于以上原理,则可以按位来比较。
         * 从低位到高位查询,遇到“1”后停止比较,所得到的数应当与原数相等,
         * 否则该数的二进制形式不止一个“1”位,即该数一定不是2的正整数次方。
         */
        ulong mask = 1ul;
        for (int count = 0;count < 64;count++)
        {
            //检查当前标识位是否为“0”
            if ((mask & value) == 0)
            {
                //当前位为“0”,则左移标识位,再次检查
                   mask <<= 1;
                continue;
            }

            /* 
             * 程序执行到此,表明当前标识位为“1”,停止检查。
             * 而此时的 mask 值正好应当与 value 相等,否则 value 就不是2的正整数次方。
             */
            return mask == value;
        }
    }
    return false;
}

感谢网友gbb21,他在此帖中提到使用如下语句,算是把这个执行效率提高到终极高度:

/// 
/// 检查是否为2的正整数次方
/// 
/// 
/// 
  
private static bool IsPowerOfTwo(ulong value)
{
    if (value > 1)
    {
        return ((value - 1) & value) == 0;
    }
    return false;
}

到此为止,我想这个算法应该没多大提升空间了吧…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值