java 2的n次方_java-获取比a大,最接近a的2的次方的数(最小二次幂,位运算)

问题描述

获取比a大,最接近a的2的次方的数-(最小二次幂) 例子:

a = 5, 返回 8;

a = 13, 返回 16;

a = 1021, 返回 1024;

位运算知识储备

**1.左移**

\->左移运算符“<

->左移m<

**2.右移**

右移运算符“>>” \- 使指定值的所有位都右移规定的次数。

右移m>>n 代表把数字m除以2的n次方,原来是正数的还是正数,负数还是负数。

注意,如果是单数,也就是二进制末位为1,则结果是将m除以2的n次方的整数商。

**3.无符号右移**

无符号右移运算符“>>>” \- 同右移,但是结果全变正数。

方法1:右移,找到 最高非0位 为第几位

static final int tableSizeFor1(int cap) {

int n = cap >> 1;

int length = 0;

while (n != 0){

n = n >> 1;

length ++;

}

return 2 << length;

}

方法2:

static final int tableSizeFor3(int cap) {

int length = 1;

while (length < cap) {

length <<= 1;

}

return length;

}

hashmap的实现方式:

static final int tableSizeFor(int cap) {

int n = cap - 1;

n |= n >>> 1;

n |= n >>> 2;

n |= n >>> 4;

n |= n >>> 8;

n |= n >>> 16;

return n + 1;

}

简单说明:

/**

* Returns a power of two size for the given target capacity.

*/

static final int tableSizeFor(int cap) {

//cap-1后,n的二进制最右一位肯定和cap的最右一位不同,即一个为0,一个为1,例如cap=17(00010001),n=cap-1=16(00010000)

int n = cap - 1;

//n = (00010000 | 00001000) = 00011000

n |= n >>> 1;

//n = (00011000 | 00000110) = 00011110

n |= n >>> 2;

//n = (00011110 | 00000001) = 00011111

n |= n >>> 4;

//n = (00011111 | 00000000) = 00011111

n |= n >>> 8;

//n = (00011111 | 00000000) = 00011111

n |= n >>> 16;

//n = 00011111 = 31

//n = 31 + 1 = 32, 即最终的cap = 32 = 2 的 (n=5)次方

return n + 1;

}

为什么右移到16位,可以得到的最大值是32个1 ? 11111111 11111111 11111111 11111111

这个是因为java的int类型用4个字节32位来进行存储的,再往后也没有意义了

int类型占4个字节(byte);

一个字节=8bit(位);

一个int类型的数值占32bit(位)int i = 123;

10进制123转为二进制后等于:1111011 。完整补位后:00000000 00000000 00000000 01111011

循环测试后,该方案最佳(不愧是jdk自带的)

其他:

求小于等于2的幂次方的数:

static final int tableSizeFor(int cap) {

int n = cap - 1;

n |= n >>> 1;

n |= n >>> 2;

n |= n >>> 4;

n |= n >>> 8;

n |= n >>> 16;

return n - (n >> 1);

}

public static void main(String[] args) {

System.out.println(tableSizeFor(31));

System.out.println(tableSizeFor(34));

}

输出:

16

32

参考链接:

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值