算法 | 寻找距离整数num最近的2的某次方

文章介绍了如何在不使用循环的情况下,通过位运算找到大于等于给定整数num的最近的2的幂次方。对于正数,利用二进制右移和或运算,而对于负数,直接返回2的0次方。代码实现中,先对num减1,然后进行一系列位运算,确保所有小于最高位1的位都变为1,最后加1得到结果。

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

前言

本文主要介绍如何寻找距离int型整数num最近的2的某次方。

要求给出一个整数num,在不使用循环语句的情况下,返回大于等于num并且距离num最近的2的某次方。

例如,num=3,距离并大于num的数为22^22;num=5,距离并大于num的数为23^33。

思路分析

num为负数

如果num为负数的话,比较简单,因为2的几次方,肯定是个正数,无论负数num为多少,大于等于num的2的某次方肯定为20^00。

num为正数

如果num为正数的话,我们从二进制上来看看如何处理。

2的n次方的二进制信息是如何表示的呢?他的二进制表现形式为,在第n位置上为1,其他位置全部为0

假如num的二进制信息为0010101001,那距离这个数的2的n次方是多少呢?只需要把num的二进制最高位的1往前移动一位,也就是0100000000

那么如何得到这个数呢?我们把0100000000这个数减去个1来看下,得出的结果为0011111111,这个数和num的二进制0010101001最高位的1是一样的,只是右边全部为1

那么接下来只需要把num的二进制信息最高位1右边变成1就可以了。

转换为1

由于不能使用循环判断,我们从位运算方面出发。

这里用到的是或运算,或运算的规则为1|1=11|0=10|0=0

我们不知道num的数值是多少,他的最高位的1有可能在0~31位的任何位置,所以要做好最坏的打算。

假设num的二进制信息为001100001,根据这个我们来看下计算过程。

  1. 001100001右移1位为0001100000,并将两个数进行或运算,结果为0011100001

  2. 0011100001右移2位为0000111000,并将两个数进行或运算,结果为0011111001

  3. 0011111001右移4位为0000001111,并将两个数进行或运算,结果为0011111111

从上面过程可以看到,经过3次右移操作,就可以把二进制001100001最高位1右侧的数全部变为1

但是,由于我们并不知道num具体是多少,所以做好最坏的打算,最坏的打算就是把32位全部变为1

所以,需要右移的位数应该为:1位、2位、4位、8位、16位。

刚好为2的某次方

如果这个num本身就为2的某次方,还能用上述的操作过程吗?也是可以的,只不过最后不需要进行加1

所以,为了保证计算逻辑的统一,我们先把num这个数一上来就进行减1操作,这样的话,如果这个num本身就为2的某次方,则运算逻辑和前面分析的一样,如果不是的话,也没什么影响。

代码实现

经过前面的逻辑分析,我们来看下代码实现,其实代码非常简单,我们一起来看下。

public class Code21_FindNear2PowerNum {
    public static int find(int num) {
        if (num <= 0) {
            return 1;
        }
        num --;
        num |= num >>> 1;
        num |= num >>> 2;
        num |= num >>> 4;
        num |= num >>> 8;
        num |= num >>> 16;
        return num + 1;
    }
    public static void main(String[] args) {
        int res = find(-15);
        System.out.println(res);
        res = find(5);
        System.out.println(res);
        res = find(11);
        System.out.println(res);
        res = find(20);
        System.out.println(res);
    }
}
复制代码

运行代码,输出结果为:

1
8
16
32
复制代码

总结

本文主要介绍如何寻找距离int型整数num最近的2的某次方,主要利用了二进制的特性以及右移运算。

如果你有更好的办法,欢迎在评论区留言交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值