本文中所提到的运算都是基于整数来说的,因为只有整数(包括正数和负数)在操作系统中是以二进制的补码形式运算的,关于原码、反码、补码、位运算、移位运算的背景这里不再介绍,网上资料很多,感兴趣的可自行搜索。

java中能表示整数数据类型的有byte、short、char、int、long,在计算机中占用的空间使用字节描述,1个字节使用8位二进制表示。

数据类型 字节数 二进制位数 表示范围 默认值
byte 1 8 -2^7 -- 2^7-1 0
char 2 16 0 -- 2^16-1 '\u0000' (代表字符为空 转成int就是0)
short 2 16 -2^15 -- 2^15-1 0
int 4 32 -2^31 -- 2^31-1 0
long 8 64 -2^63 -- 2^63-1 0L

原码、反码、补码

使用位运算前需要先弄清楚这几个概念

原码

原码也叫机器码,整数的二进制形式表示,最高位为符号位。1表示负数,0表示正数,除去符号位后剩余其他的所有位是该整数的绝对值的二进制值。

int a = 7; //原码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//原码二进制表示为:10000000 00000000 00000000 00000111

反码

反码需要区分是正数还是负数,正数的反码跟原码相同,负数的反码是除符号位外,其他位取反(即负数的最高位是1不变,其他位0变成1,1变成0)。

int a = 7; //反码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//反码二进制表示为:11111111 11111111 11111111 11111000

补码

补码也需要区分是正数还是负数,正数的补码跟原码相同,负数的补码是反码最低位加1。

int a = 7; //补码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//补码二进制表示为:11111111 11111111 11111111 11111001

说完了概念,其实这里的原码是方便给人看的,对于计算机运算来说都是使用补码形式操作。以下的位运算和移位运算都是基于补码进行的。

位运算

位运算术语解释

位运算符 含义 解释 备注
& 按位与 两个整数按位对齐,当对齐的两位同时为1则结果为1,否则为0
| 按位或 两个整数按位对齐,当对齐的两位只要有一个为1则结果为1,否则为0
~ 按位非 只能适用于一个整数的自身操作,按位取反,即1变成0,0变成1 单目运算符
^ 按位异或 两个整数按位对齐,当对齐的两位相同时为0,否则为1

位运算示例

我们以上面的int a = 7和int b = -7举例位运算的操作。

a的补码二进制为:00000000 00000000 00000000 00000111

b的补码二进制为:11111111 11111111 11111111 11111001

1、a&b

按位与的结果补码为:00000000 00000000 00000000 00000001
因为最高位为0,所以为正数,`正数的原码反码补码都相同`,所以原码也为:
00000000 00000000 00000000 00000001
转换成十进制的结果就是1。

2、a|b

按位或的结果补码为:11111111 11111111 11111111 11111111
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11111110
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000001
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是1,所以最后按位或的结果就是-1。

3、a^b

按位或的结果补码为:11111111 11111111 11111111 11111110
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11111101
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000010
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是2,所以最后按位或的结果就是-2。

4、~a

取反结果(补码形式):11111111 11111111 11111111 11111000
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11110111
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00001000
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是8,所以最后按位或的结果就是-8。

5、~b

取反结果(补码形式):00000000 00000000 00000000 00000110
最高位为0,所以是正数。正数的原码反码补码都相同,所以转换成十进制结果为6。

位运算应用于boolean操作

&(与)、|(或)这两个位运算适用于boolean判断,在这两个运算符的前后的条件都会计算,不像java里的条件判断符&&(并且) ||(或者)会短路,判断符之前的满足条件后,那么判断符之后的表达式不再计算。

public static void main(String[] args) {
int a = 5;
if (a < 0 & a++ > 0) {
}
System.out.println("&条件后a=" + a);
if (a > 0 | a++ > 0) {
}
System.out.println("|条件后a=" + a);
if (a < 0 && a++ > 0) {
}
System.out.println("&&条件后a=" + a);
if (a > 0 || a++ > 0) {
}
System.out.println("||条件后a=" + a);
}

输出结果为:

&条件后a=6
|条件后a=7
&&条件后a=7
||条件后a=7

第一个判断a < 0 & a++ > 0前一个判断已经是false了,但是使用&连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于6。

第二个判断a > 0 | a++ > 0前一个判断已经是true了,但是使用|连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于7。

第三个判断a < 0 && a++ > 0前一个判断已经是false了,使用&&连接的不会再计算后一个表达式的值,所以a的值不变。

第四个判断a > 0 || a++ > 0前一个判断已经是true了,使用||连接的不会再计算后一个表达式的值,所以a的值不变。

移位运算

移位运算术语解释

移位运算符 含义 解释
<< 左移 补码高位(不包括符号位)去掉指定位数,然后剩下的位数整体向左移动指定位数,低位使用0补齐
>> 右移 补码低位去掉指定位数,然后剩下的位数整体向右移动指定位数,高位补上符号位(即正数补0,负数补1)
>>> 无符号右移 这个主要是针对于负数来说的,补码低位去掉指定位数,然后剩下的位数整体向右移动指定位数,高位(包括符号位)全部补上0

移位运算也是基于补码来操作的,因为是采用二进制,所以左移n位相当于该数乘以2的n次方、右移及无符号右移n位相当于该数除以2的n次方,但是无符号右移是相对于负数来说的,把符号位和其他高位都置为0。

移位运算示例

我们仍以上面的int a = 7和int b = -7举例移位运算的操作。

a的补码二进制为:00000000 00000000 00000000 00000111

b的补码二进制为:11111111 11111111 11111111 11111001

1、a<<2

符号位不变,高位去掉两位,整体左移两位,低两位补0,结果为:
补码:00000000 00000000 00000000 00011100
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:28

2、a>>2

符号位为0,正数,则符号位不变,低位去掉两位,整体右移两位,高两位补0,结果为:
补码:00000000 00000000 00000000 00000001
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1

3、a>>>2

符号位为0,正数,低位去掉两位,整体右移两位,高两位(包括符号位)补0,结果为:
补码:00000000 00000000 00000000 00000001
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1

4、b<<2

符号位不变,高位去掉两位,整体左移两位,低两位补0,结果为:
补码:11111111 11111111 11111111 11100100
高位为1即负数
反码=补码-1,得到反码:11111111 11111111 11111111 11100011
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00011100
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是28,所以最后按位或的结果就是-28。

5、b>>2

符号位为1,负数,低位去掉两位,整体右移两位,高两位补1,符号位为1,结果为:
补码:11111111 11111111 11111111 11111110
高位为1即负数
反码=补码-1,得到反码:11111111 11111111 11111111 11111101
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000010
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是2,所以最后按位或的结果就是-2。

6、b>>>2

符号位为1,负数,低位去掉两位,高两位(包括符号位)都补0,结果为:
补码:00111111 11111111 11111111 11111110
高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1073741822。

移位运算注意事项

1、byte、short、char类型的整数再移位操作时会自动向上转为int类型后再操作移位。

2、int类型占32位,long类型占64位,当对这两个类型移位超出位数时,相当于对要移动的位数取余再移位,例如a<<32位,取余为0,相当于不移动,a<<34,取余为2相当于左移2位。long类型同理,只是对64取余。

应用

1、不利用中间值,交换两个整数

可推倒出的结论是 aba=b,abc= a(bc)。所以对于两个整数a,b交换可以使用异或位运算。

public static void main(String[] args) {
int a = 5, b = 3;
System.out.println("a=" + a + "\tb=" + b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("a=" + a + "\tb=" + b);
}

输出结果:

a=5	b=3
a=3 b=5

2、判断一个正数的奇偶性

x & 1 == 0 则为偶数,否则为奇数。因为整数的二进制表示后,最后一位的0和1就表示了该值的奇偶性,&1之后相当于除了最后一位,其他位全清0了,最后一位若是1,则与的结果才为1,说明是奇数,最后一位为0,则与的结果是0,说明是偶数。

3、判断一个正数是不是2的幂次方

使用n&(n-1) == 0则为偶数,否则为奇数。因为2的次方数,除了高位的一个1外,后面的数据全部都是0,也就是说2的次方数的二进制形式里只有一个1,其他全部是0,减1后得到的二进制,1所在位变成0,1后的其他位都会变成1,所以与原二进制每一位都不相同,使用&后结果为0,则可以证明为偶数

4、计算一个二进制数中1的个数

int a = 15;
int count = 0;
while (a != 0) {
if ((a & 1) == 1) {
count++;
}
a = a >> 1;
}
System.out.println(count);

通过&1结果为1,说明最末一位是1,则可通过不断>>1并判断1的个数是否加1,直到这个数的值变为0为止。

5、其他应用场景可自行探索(* ̄︶ ̄)

java位运算及移位运算你还记得吗的更多相关文章

  1. JAVA:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题(5)

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  2. Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  3. Java中的位运算符、移位运算

    一.位运算 Java中有4个位运算,它们的运算规则如下: (1)按位与 (&)  :两位全为1,结果为1,否则为0: (2)按位或  (|)   :两位有一个为1,结果为1,否则为0: (3) ...

  4. java中位运算和移位运算详解

    一.位运算 (1)按 位 与 & 如果两个相应的二进制形式的对应的位数都为1,则结果为1,记为同1为1,否则为0.首先我们看一下对正数的运算        分别看一下正数和负数的具体运算步骤 ...

  5. java中的位运算及移位运算

    为了方便对二进制位进行操作,Java给我们提供了以下四个二进制位操作符: &    按位与 |     按位或 ^    按位异或 ~    按位取反 Java中有三个移位运算符: 左移:&l ...

  6. C语言位运算、移位运算 经典示例

    概述: C语言的位级运算可以运用到任何“整数”的数据类型上,如char.short.int.long.long long.或者unsigned这样的限定词.基本的位运算有与.或.非.异或等等. C语言 ...

  7. Java 位运算符和移位运算符

    一,运算的位运算符: &  ~ |  ^     主要是对二进制的位计算 :   &  : 两个操作数中位都为1 结果才为1   其他结果为0      forExample: 128 ...

  8. 我们必须要了解的Java位运算(不仅限于Java)

    本文原创地址为 https://www.cnblogs.com/zh94/p/16195373.html 原创声明:作者:陈咬金. 博客地址:https://www.cnblogs.com/zh94/ ...

  9. java位运算

    Java的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long.int.short.char和 byte,位运算符具体如下表: 运算符 说明 << ...

  10. 【原创】Java移位运算

    学习移位运算,首先得知道参与移位运算的类型的位数,那先来复习下Java基础类型的占位数吧. Java基础类型 Java基础类型总结一览表 类型 二进制位数 最大值 最小值 初始化值 表示形式 带符号 ...

随机推荐

  1. 分享一个提高运维效率的 Python 脚本

    哈喽大家好我是咸鱼,今天给大家分享一个能够提升运维效率的 python 脚本 咸鱼平常在工作当中通常会接触到下面类似的场景: 容灾切换的时候批量对机器上的配置文件内容进行修改替换 对机器批量替换某个文 ...

  2. 2021-07-05:股票问题2。给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖

    2021-07-05:股票问题2.给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格.设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖 ...

  3. Spring源码:Bean生命周期(四)

    前言 在之前的文章中,我们介绍了 Bean 的核心概念.Bean 定义的解析过程以及 Bean 创建的准备工作.在今天的文章中,我们将深入探讨 Bean 的创建过程,并主要讲解 createBean ...

  4. import MySQLdb as Database ModuleNotFoundError: No module named ‘MySQLdb‘

    import MySQLdb as Database ModuleNotFoundError: No module named 'MySQLdb' import MySQLdb as Database ...

  5. 2023.5.16 总结 AT_abc260_g

    atcoder AT_abc260_g 题意 一个点 O 可以影响到其它点,能影响到的点的坐标满足:(\((u, v)\) 为当前点的坐标,\((x, y) 为能影响到的点的坐标\)) \(u\le ...

  6. 【LeetCode双向链表】LRU详解,双向链表实战

    LRU缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构. 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity ...

  7. .NET 创建无边框的跨平台应用

    .NET 创建无边框的跨平台应用 在创建了Photino应用程序以后我们发现它自带了一个标题栏,并且非常丑,我们现在要做的就是去掉这个很丑的自带标题栏,并且自定义一个更好看的,下面我们将用Masa B ...

  8. 时间不等人,但 Moment.js 可以等你解决时间问题!

    前言 一直以来,处理时间和日期的JavaScript库,选用的都是Moment.js.它的API清晰简单,使用方便灵巧,功能还特别齐全. 我是Moment.js的重度使用者.凡是遇到时间和日期的操作, ...

  9. celery笔记四之在Django中使用celery

    本文首发于公众号:Hunter后端 原文链接:celery笔记四之在Django中使用celery 这一篇笔记介绍一下如何在 Django 系统中使用 celery. 如果是想纯粹使用 celery, ...

  10. 流程挖掘里程碑:国产RPA首次入选顶级行业报告

    正在成为组织运营标配的流程挖掘,到底有哪些商业价值? 作为超级自动化的重要先驱,流程挖掘正在成为组织运营标配 文/王吉伟 AIGC正在影响越来越多的行业,流程挖掘领域亦不例外. Mindzie首先宣布 ...