Java 中的移位运算符(Shift Operator)

2023年 9月 4日 78.0k 0

针对移位(Shift Operator)操作符是最基本的操作符之一,几乎每种编程语言都包含这一操作符。

同时我们对移位运算又会觉得比较陌生和困惑,这是因为移位运算除了在 JDK 底层你会遇到不少,还有就是在各种奇葩的面试题会遇到一些,在实际使用的时候,这个运算其实很难用得上。

因为用得不多,所以在大部分人的面对的代码情况下,根本不会考虑移位运算,所以对移位运算我们大致知道下就可以了,至于如何奇葩的运算,你只知道一些基本概念就行,其实很多时候并不需要你直接用移位运算算出来。

基本概念

针对移位运算,我们需要了解有几个基本概念。

3 个移位运算符

Java 只有 3 个移位运算符, (带符号右移)和 >>> (无符号右移)。

为什么有 3 个,移位运算不是左就是右,为什么有 3 个?

因为 Java 的整数是有符号的整数,所以针对符号转换 Java 添加了一个无符号右移。

只能用于整数

Java 的移位运算,不能用于浮点数,只能用于整数。

因为 Java 可以处理整数的长度不一样,所以移位运算只会用在 int 上,虽然其他数据类型也可以用,但是都是在转换成 int 后进行计算的。

类型

长度

long

64 位

int

32 位

short

16 位

byte

8 位

char

8 位

整数 2 进制表达

在 Java 的整数 int 表达中,其中有一个位留给了符号位置,所以真正可以存储数据的位为 31 位。

因此,Int 的存储范围为:[-2^31,2^31-1],所以上面的指数为 31, 而不是 32 的原因是其中有一位留给了符号位。

左移操作符 </h2
p左移操作符 code/code 是将数据转换成二进制数后,strong向左移若干位,高位丢弃,低位补零/strong 。/p
p如下面的代码:/p
precode lang="less" spanlog/spanspan.debug/span(span"{}/{}"/span, Integer.spantoBinaryString/span(span12/span), Integer.spanparseInt/span(Integer.spantoBinaryString/span(span12/span), span2/span));
spanlog/spanspan.debug/span(span"{}/{}"/span, Integer.spantoBinaryString/span(span12/span < span1/span), Integer.spanparseInt/span(Integer.spantoBinaryString/span(span12/span < span1/span), span2/span));
spanlog/spanspan.debug/span(span"{}/{}"/span, Integer.spantoBinaryString/span(span12/span < span8/span), Integer.spanparseInt/span(Integer.spantoBinaryString/span(span12/span 8));

运行结果为:

12:25:32.765 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111110100
12:25:32.765 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111111010
12:25:32.765 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111111111

我们可以看到上面的移位为带有符号的移位置,所有移动的高位在负数的时候都被补充为符号位了。

如果是负数的话,就会补充为 1 。

无符号右移操作符 >>>

无符号右移操作符 >>>>> 类似,都是将数据转换为二进制数后右移若干位,不同之处在于,不论负数与否,结果都 是高位补零,低位丢弃 。

这个操作符的计算对负数的计算会因为补位的不同而变成整数。

如下面的代码。

        log.debug("---- Shift Operator >>> ---");
        log.debug("{}", Integer.toBinaryString(-12));
        log.debug("{}/{}", Integer.toBinaryString(-12 >>> 1), Integer.parseInt(Integer.toBinaryString(-12 >>> 1), 2));
        log.debug("{}/{}", Integer.toBinaryString(-12 >>> 8), Integer.parseInt(Integer.toBinaryString(-12 >>> 8), 2));

程序输出如下:

13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - ---- Shift Operator >>> ---
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111110100
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 1111111111111111111111111111010/2147483642
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 111111111111111111111111/16777215

2023-09-03_13-27-11

从上面的代码输出中,我们会发现对应的 2 进制长度不一样,因为在 Java 程序中对于二进制,前面为 0 的时候,在输出的时候会进行丢弃的。

所以显示的长度不一样,如果希望显示长度一致的话,前面补 0 就可以了。

www.ossez.com/t/java-shif…

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论