前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员必须掌握的位运算,因为...

程序员必须掌握的位运算,因为...

作者头像
田维常
发布2020-05-22 16:57:48
3730
发布2020-05-22 16:57:48
举报
文章被收录于专栏:Java后端技术栈cwnait

背景

HashMap源码中有过这么一段代码

代码语言:javascript
复制
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 < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

如果你不会位运算的话,这段代码基本上是看不懂的。

什么是位运算?

计算机在底层使用的是二进制补码进行运算。对应的二进制位进行操作,计算机只识别0和1 。

位运算有什么好处?

巧妙的使用位运算可以大量减少运行开销,优化算法。

Java中支持哪些位运算?
使用案例

复合赋值运算符

位运算符与赋值运算符结合,组成新的复合赋值运算符,它们是:

  • &= 例:a&=b 相当于 a=a&b
  • |= 例:a|=b 相当于 a=a|b
  • >>= 例:a>>=b 相当于 a=a>>b
  • <<= 例:a<<=b 相当于 a=a<<b
  • ^= 例:a^=b 相当于 a=a^b

不同长度的数据进行位运算

如果两个不同长度的数据进行位运算时,系统会将二者按右端对齐,然后进行位运算。

以“与运算”为例说明如下:

我们知道在 C 语言中 long 型占 4 个字节,int 型占 2 个字节,如果一个 long 型数据与一个 int 型数据进行“与运算”,右端对齐后,左边不足的位依下面三种情况补足。

  • 如果整型数据为正数,左边补 16 个 0 例如:long a=123,int b=1,计算 a&b
  • 如果整型数据为负数,左边补 16 个 1 例如:long a=123,int b=-1,计算 a&b
  • 如果整形数据为无符号数,左边也补 16 个 0 例如:long a=123,unsigned intb=1,计算 a&b

回到本文最前面的那段代码

代码语言:javascript
复制
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 < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

参数 cap 的值肯定大于 0,故 n 大于等于 0 ,假设 n = 0,经过右移之后,依旧为 0 ,0 与 0 异或依旧为 0 ,通过 return 语句的 n+ 1 计算得 1,即 2 的 0 次幂。

当 n 大于 0 时,n 的二进制位肯定会有位的值为 1,即 001xx..xx 的形式,接着,对 n 右移 1 位得 0001xx..xx,再进行位或,由于 1 与 0 或 1 异或结果都为 1,所以结果必为 0011xx..xx 的形式。以此类推,位移 2 位、4 位、8 位、 16 位,最终该算法能让最高位的 1 后面的所有位全变为 1。

下面用一张图举例说明一下:

该算法的最后再让结果值 n + 1,所得即为 2 的整数次幂。为了让结果使结果大于等于参数 cap,在算法开始时,令 cap - 1。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是位运算?
  • 位运算有什么好处?
  • Java中支持哪些位运算?
  • 使用案例
  • 复合赋值运算符
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档