欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 左移右移等移位运算

左移右移等移位运算

2025/5/18 23:52:57 来源:https://blog.csdn.net/wang0907/article/details/141156583  浏览:    关键词:左移右移等移位运算

写在前面

如果是看过jdk的源码的话,可能会经常看到移位操作,比如:
在这里插入图片描述
在这里插入图片描述
因为这种移位操作效率高,并且书写简单,所以应用的还是比较广泛的,本文一起来看下,希望在工作中能真正的在合适的场景中用起来!

1:有符号移位操作(算数移位)

知识点:

1:符号位不参与移位
2:移出的位直接丢弃

1.1:正数有符号→移操作>>

以正数10为例,其二进制是00000000 00000000 00000000 00001010,执行>>1如下:

00000000 00000000 00000000 00001010
>>1
00000000 00000000 00000000 00000101 0 丢弃移出最右侧的一个0 
结果:00000000 00000000 00000000 00000101

测试:

package org.example;public class AAA {public static void main(String[] args) {int oldCapacity = 10;
//        System.out.println(oldCapacity >> 1); // 5
//        System.out.println(Integer.toString(oldCapacity >> 1, 2));System.out.println("---移位操作前---");System.out.println(showWithBinary(Integer.toString(oldCapacity, 2)));String s = Integer.toString(oldCapacity >> 1, 2);System.out.println("---移位操作后---");System.out.println(showWithBinary(s));}private static String showWithBinary(String s) {
//        System.out.println("原始十进制数:" + s);int spanZeroNum = 32 - s.length();StringBuffer spanZeroSb = new StringBuffer();int oneEight = 0;while (spanZeroNum-- > 0) {spanZeroSb.append("0");if (++oneEight % 8 == 0) spanZeroSb.append(" ");}
//        System.out.println(spanZeroSb.toString() + s);return "转换为二进制表示:" + spanZeroSb.toString() + s;}
}

运行:

---移位操作前---
转换为二进制表示:00000000 00000000 00000000 00001010
---移位操作后---
转换为二进制表示:00000000 00000000 00000000 00000101Process finished with exit code 0

1.2:负数有符号→移操作>>

负数:高位插入1
以负数-10为例,其二进制原码是10000000 00000000 00000000 00001010(注意转换为补码,负数是以补码形式存储的),执行>>1如下:

10000000 00000000 00000000 00001010
反码:
11111111 11111111 11111111 11110101
+1得到补码:
11111111 11111111 11111111 11110110
>>1(符号为不参与移位)

得到111111111 11111111 11111111 11110110,高亮的是高位插入的1:

111111111 11111111 11111111 11110110
右侧移出的直接丢弃,得到结果:
111111111 11111111 11111111 1111011
整理8 8 8 8形式:
11111111 11111111 11111111 11111011

想要看结果还需要转换成其原码:

11111111 11111111 11111111 11111011
-1
11111111 11111111 11111111 11111010
反码:
10000000 00000000 00000000 00000101 即-5

所以运算是通过补码进行的,但是肉眼想要得到实际的结果还需要转换为原码来查看。
测试:

package org.example;public class AAA {public static void main(String[] args) {int oldCapacity = -10;
//        System.out.println(oldCapacity >> 1); // 5
//        System.out.println(Integer.toString(oldCapacity >> 1, 2));System.out.println("---移位操作前---");System.out.println(showWithBinary(Integer.toString(oldCapacity, 2)));String s = Integer.toString(oldCapacity >> 1, 2);System.out.println("---移位操作后---");System.out.println(showWithBinary(s));}private static String showWithBinary(String s) {
//        System.out.println("原始十进制数:" + s);String signBit = s.startsWith("-") ? "1" : "0";s = s.replace("-", "");int spanZeroNum = 32 - s.length();StringBuffer spanZeroSb = new StringBuffer();int oneEight = 0;while (spanZeroNum-- > 0) {if (oneEight == 0) spanZeroSb.append(signBit);else spanZeroSb.append("0");if (++oneEight % 8 == 0) spanZeroSb.append(" ");}
//        System.out.println(spanZeroSb.toString() + s);return "转换为二进制表示:" + spanZeroSb.toString() + s;}
}

运行:

---移位操作前---
转换为二进制表示:10000000 00000000 00000000 00001010
---移位操作后---
转换为二进制表示:10000000 00000000 00000000 00000101Process finished with exit code 0

1.3:正数有符号←移操作<<

以正数10为例,其二进制是00000000 00000000 00000000 00001010,执行<<1如下:

00000000 00000000 00000000 00001010
>>1
00000000 00000000 00000000 00010100
结果:20

测试:

package org.example;public class AAA {public static void main(String[] args) {int oldCapacity = 10;
//        System.out.println(oldCapacity >> 1); // 5
//        System.out.println(Integer.toString(oldCapacity >> 1, 2));System.out.println("---移位操作前---");System.out.println(showWithBinary(Integer.toString(oldCapacity, 2)));String s = Integer.toString(oldCapacity << 1, 2);System.out.println("---移位操作后---");System.out.println(showWithBinary(s));}private static String showWithBinary(String s) {
//        System.out.println("原始十进制数:" + s);String signBit = s.startsWith("-") ? "1" : "0";s = s.replace("-", "");int spanZeroNum = 32 - s.length();StringBuffer spanZeroSb = new StringBuffer();int oneEight = 0;while (spanZeroNum-- > 0) {if (oneEight == 0) spanZeroSb.append(signBit);else spanZeroSb.append("0");if (++oneEight % 8 == 0) spanZeroSb.append(" ");}
//        System.out.println(spanZeroSb.toString() + s);return "转换为二进制表示:" + spanZeroSb.toString() + s;}
}

运行:

---移位操作前---
转换为二进制表示:00000000 00000000 00000000 00001010
---移位操作后---
转换为二进制表示:00000000 00000000 00000000 00010100Process finished with exit code 0

1.4:负数有符号←移操作<<

低位补0
以负数数-10为例,其二进制补码是11111111 11111111 11111111 11110110,执行<<1如下:

11111111 11111111 11111111 11110110
<<1
1111111 11111111 11111111 111101100
整理成8888形式:
11111111 11111111 11111111 11101100
转换为原码
先-1:
11111111 11111111 11111111 11101011
再取反:
10000000 00000000 00000000 00010100 即-20

测试:

package org.example;public class AAA {public static void main(String[] args) {int oldCapacity = -10;
//        System.out.println(oldCapacity >> 1); // 5
//        System.out.println(Integer.toString(oldCapacity >> 1, 2));System.out.println("---移位操作前---");System.out.println(showWithBinary(Integer.toString(oldCapacity, 2)));String s = Integer.toString(oldCapacity << 1, 2);System.out.println("---移位操作后---");System.out.println(showWithBinary(s));}private static String showWithBinary(String s) {
//        System.out.println("原始十进制数:" + s);String signBit = s.startsWith("-") ? "1" : "0";s = s.replace("-", "");int spanZeroNum = 32 - s.length();StringBuffer spanZeroSb = new StringBuffer();int oneEight = 0;while (spanZeroNum-- > 0) {if (oneEight == 0) spanZeroSb.append(signBit);else spanZeroSb.append("0");if (++oneEight % 8 == 0) spanZeroSb.append(" ");}
//        System.out.println(spanZeroSb.toString() + s);return "转换为二进制表示:" + spanZeroSb.toString() + s;}
}

运行:

---移位操作前---
转换为二进制表示:10000000 00000000 00000000 00001010
---移位操作后---
转换为二进制表示:10000000 00000000 00000000 00010100

Process finished with exit code 0

2:无符号移位操作(逻辑移位)

符号位也参与移位,移出的位直接丢弃。

2.1:正数无符号→移操作>>>

以正数10为例,其二进制是00000000 00000000 00000000 00001010,执行>>>1如下:

00000000 00000000 00000000 00001010
>>>1
00000000 00000000 00000000 00000101 0 丢弃移出最右侧的一个0 
结果:00000000 00000000 00000000 00000101

测试:

package org.example;public class AAA {public static void main(String[] args) {int oldCapacity = 10;
//        System.out.println(oldCapacity >> 1); // 5
//        System.out.println(Integer.toString(oldCapacity >> 1, 2));System.out.println("---移位操作前---");System.out.println(showWithBinary(Integer.toString(oldCapacity, 2)));String s = Integer.toString(oldCapacity >>> 1, 2);System.out.println("---移位操作后---");System.out.println(showWithBinary(s));}private static String showWithBinary(String s) {
//        System.out.println("原始十进制数:" + s);String signBit = s.startsWith("-") ? "1" : "0";s = s.replace("-", "");int spanZeroNum = 32 - s.length();StringBuffer spanZeroSb = new StringBuffer();int oneEight = 0;while (spanZeroNum-- > 0) {if (oneEight == 0) spanZeroSb.append(signBit);else spanZeroSb.append("0");if (++oneEight % 8 == 0) spanZeroSb.append(" ");}
//        System.out.println(spanZeroSb.toString() + s);return "转换为二进制表示:" + spanZeroSb.toString() + s;}
}

运行:

---移位操作前---
转换为二进制表示:00000000 00000000 00000000 00001010
---移位操作后---
转换为二进制表示:00000000 00000000 00000000 00000101Process finished with exit code 0

因为是正数,所以效果和>>是一样的。

2.2:负数无符号→移操作>>>

以负数数-10为例,其二进制补码是11111111 11111111 11111111 11110110,注意因为>>>会让符号位也参与移位,而高位补0,所以,负数>>>会变成正数,执行>>>1如下:

11111111 11111111 11111111 11110110 
>>>1
011111111 11111111 11111111 1111011

测试程序:

package org.example;public class AAA {public static void main(String[] args) {int oldCapacity = -10;
//        System.out.println(oldCapacity >> 1); // 5
//        System.out.println(Integer.toString(oldCapacity >> 1, 2));System.out.println("---移位操作前---");System.out.println(showWithBinary(Integer.toString(oldCapacity, 2)));System.out.println(oldCapacity >>> 1);String s = Integer.toString(oldCapacity >>> 1, 2);System.out.println("---移位操作后---");System.out.println(showWithBinary(s));}private static String showWithBinary(String s) {
//        System.out.println("原始十进制数:" + s);String signBit = s.startsWith("-") ? "1" : "0";s = s.replace("-", "");int spanZeroNum = 32 - s.length();StringBuffer spanZeroSb = new StringBuffer();int oneEight = 0;while (spanZeroNum-- > 0) {if (oneEight == 0) spanZeroSb.append(signBit);else spanZeroSb.append("0");if (++oneEight % 8 == 0) spanZeroSb.append(" ");}
//        System.out.println(spanZeroSb.toString() + s);return "转换为二进制表示:" + spanZeroSb.toString() + s;}
}

输出:

---移位操作前---
转换为二进制表示:10000000 00000000 00000000 00001010
2147483643
---移位操作后---
转换为二进制表示:01111111111111111111111111111011Process finished with exit code 0

这里要注意,常规思维上的符号位在这种移位操作下也被当作

3:需要注意的点

3.1:负数的空位补0还是补1

有符号右移,负数:高位补1。
负数有符号←移操作低位补0。

3.2:为啥没有<<<

不知道你注意到没有,没有所谓的无符号左移操作<<<,这是因为,无符号左移会丢掉符号位,你可能会说,补一个符号位不就完了吗,补不了,为什么?因为高位已经被来自低位的数据给占据了。所以<<<没有任何意义,进一步所以就没有提供这种移位运算方式了。

写在后面

参考文章列表

JAVA基础之移位操作 。

为什么右移有「有无」符号之别,而左移却没有? 。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词