Java中的位运算符

举报
一头小山猪 发表于 2021/03/25 22:20:04 2021/03/25
【摘要】 写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成,愿将昔日所获与大家交流一二,希望对学习路上的你有所助益。同时,博主也想通过此次尝试打造一个完善的技术图书馆,任何与文章技术点有关的异常、错误、注...

写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成,愿将昔日所获与大家交流一二,希望对学习路上的你有所助益。同时,博主也想通过此次尝试打造一个完善的技术图书馆,任何与文章技术点有关的异常、错误、注意事项均会在末尾列出,欢迎大家通过各种方式提供素材。

  • 对于文章中出现的任何错误请大家批评指出,一定及时修改。
  • 有任何想要讨论和学习的问题可联系我:zhuyc@vip.163.com。
  • 发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。

Java中的位运算符

本文关键字:位运算符、位逻辑运算符、移位运算符、异或运算

一、位运算符

大家在接触运算符的时候通常都已经学完了变量的使用,对于算术以及赋值运算的感觉就是So easy!这不就是小学的知识嘛,对于逻辑运算符的部分依然无压力,这不就是中学的知识嘛?但是突然出现了一个位运算符,啥是移位?啥是异或?接下来就先从简单的开始。
说起位运算符,其实就是基于数据存储的二进制位进行的运算,更底层,所以效率更高。另外一个需要注意的问题就是:由于小数在进行存储的时候采用的是IEEE(符号、指数、尾数)方式,并不止对整数和小数部分直接转换为二进制来存储的,所以小数是不能使用位运算符来操作的。对于整数和字符型的运算符操作也有一些潜在的法则,相信看完这篇文章你很容易就会掌握。

二、逻辑运算

在逻辑运算中我们已经使用过能够表达逻辑意义的运算符,如:&&,||,!。这些运算符都有一个共同点,那就是:运算符两边都是布尔值或布尔表达式,他们能够操作的数据类型有限,只能够帮我们进行逻辑运算。有些教材将&,|等位运算符也归为逻辑运算符,因为按位与(&)、按位或(|)能够操作的数据类型较多,其中就包括布尔类型,并且也能够帮助我们进行逻辑运算,但是小编还是建议按照符号本身的运算方式和操作数据类型等来记忆。

1. 与(&)

  • 与运算

与运算相当于物理电路中的串联电路,我们假设用1代表通路,用0代表断路,那么对于串联电路来说,只有当运算符两边全为1(通路)时,运算结果才为1(通路)。
在这里插入图片描述
在这里插入图片描述

  • 按位与

那么按位与就是将运算符两边的数字转换为二进制后,在每两个对应位置上的数字进行与运算,再将最后的结果按十进制写出就可以了。
24 & -30:
00000000 00000000 00000000 00011010 = 26
11111111 11111111 11111111 11100010 = -30
00000000 00000000 00000000 00000010 = 26 & -30 = 2

  • 逻辑与的短路问题

当我们在使用逻辑与(&&)时会遇到一个短路问题:当用&&把多个布尔表达式连接起来的时候,为了以最快的速度得出结果,那么有些式子将不会执行,被跳过的式子中的代码也就不会被执行。比如:(假式 && 真式 && 真式),经过前两个式子的结果已经能够确定整个式子的结果:为假,第三个式子无论为真或假都不会影响最终结果,这个时候就会进行跳过。
但是对于&(按位与),由于本质上是一个位运算,只不过同时也支持布尔类型的直接运算而已,所以不会出现表达式不执行的情况。

2. 或(|)

  • 或运算

或运算相当于物理电路中的并联电路,我们假设用1代表通路,用0代表断路,那么对于并联电路来说,只要运算符两边有一个为1(通路)时,运算结果就为1(通路)。
在这里插入图片描述
在这里插入图片描述

  • 按位或

那么按位或就是将运算符两边的数字转换为二进制后,在每两个对应位置上的数字进行或运算,再将最后的结果按十进制写出就可以了。
26 | -30:
00000000 00000000 00000000 00011010 = 26
11111111 11111111 11111111 11100010 = -30
11111111 11111111 11111111 11111010 = 26 | -30 = -6

  • 逻辑或的短路问题

当我们在使用逻辑或(||)时会遇到一个短路问题:当用||把多个布尔表达式连接起来的时候,为了以最快的速度得出结果,那么有些式子将不会执行,被跳过的式子中的代码也就不会被执行。比如:(真式 || 假式 && 假式),经过前两个式子的结果已经能够确定整个式子的结果:为真,第三个式子无论为真或假都不会影响最终结果,这个时候就会进行跳过。
但是对于|(按位与),与按位或相同,是一个位运算符,不会出现跳过的情况。

3. 取反(~)

  • 运算规则

取反运算的规则相对简单,同样是在二进制位上的运算,那么遇到0变为1,遇到1变为0。
在这里插入图片描述

  • 实用公式

对于一个数n的取反可以按照公式快读得出结果:~n = -n - 1

4. 异或(^)

  • 运算规则:

其实异或的运算规则很好记,对对碰原则,两个数相同为0,不同为1,如下表:
在这里插入图片描述

  • 运算律:
    • a ^ a = 0
    • 交换律:a ^ b = b ^ a
    • 结合律:a ^ (b ^ c) = (a ^ b) ^ c
    • a ^ b ^ a = b
  • 两数交换的用法:

如果我们需要将两个数交换,一般都需要引入第三个变量,作为中间变量或进行运算实现。其实,我们还可以利用异或运算的规律来实现:不借助第三个变量来实现两个数的交换。
a = a ^ b;
b = a ^ b; -> 使用交换律:b = (a ^ b) ^ b = (b ^ a) ^ b = a
a = a ^ b; -> 此时b的值为a,a的值为:(a ^ b) -> a = (a ^ b) ^ a = b
特别注意:虽然异或可以用于两个数的交换,但是由于异或有一个特别的性质,即a ^ a = 0,所以当两个数相等时,会导致两个数都变为0

三、移位运算

特别注意:对于位移运算不能直接和除法的结果等同,在负数时将不相等

1. 左移(<<)

将一个整数的二进制位向左平移指定的位数,由于是左移就相当于是扩大了数值,并且每移动一位,相当于扩大了二倍。

  • 移出的高位将被丢弃
  • 右侧补零

由于正数的高位都是0,负数的高位都是1,所以在一定的范围内,经过向左移位不会改变数字的正负。但如果超出了一定的范围,将会改变数字的正负,并且会充满随机性,正负性将取决于最高位(符号位)的数值。
-7 << 2 = -28
-7 << 30 = 1073741824

2. 右移(>>)

将一个整数的二进制位向右平移指定的位数,由于是右移就相当于是缩小了数值,并且每移动一位,相当于缩小了二倍。

  • 移出的低位将被丢弃
  • 若为正数,高位补0
  • 若为负数,高位补1

由于符号位在高位的部分,并且在移动的过程中的补位也是根据正负的规则在补,所以右移不会改变正负。

3. 无符号右移(>>>)

无符号右移的计算规则与右移相同,区别在于,不会进行正负的区分,高位一律用0补位。如果原数是一个负数,则可能直接得到一个非常大的正数。

  • -27 >> 2 = -7
  • -27 >>> 2 = 1073741817

四、运算规则

1. 运算符两边精度不一致

  • 需要先进行精度的统一,即以高精度为准,低精度的数据进行补位
    • 正数高位补0
    • 负数高位补1

2. 移位运算规则

  • 移动的位数不应该超过该数字对应的二进制位数

    • 得到的结果无数学意义
    • 会得到一些极端值结果
  • 对于负数在内存中的存储不清楚的可以参考这篇文章:为什么一个byte的存储范围是-128~127?

在这里插入图片描述

文章来源: blog.csdn.net,作者:小山猪的沙塔,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/u012039040/article/details/103376010

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。