Java——左移、右移和其他特殊运算符

news2024/11/18 11:31:34
  • 😜           :是江迪呀
  • ✒️本文关键词微信小程序页面跳转移动端前端
  • ☀️每日   一言我宁要痛苦不要麻木!

在这里插入图片描述

一、前言

当涉及位操作和位级运算时,Java 提供了一组特殊的运算符,即左移(<<)和右移(>>)运算符。这些运算符与普通的算术和逻辑运算符不同,它们操作的是数字的二进制位。位操作是计算机底层编程中常用的技巧,能够高效地执行一些操作,如数值乘除以2的幂次方,处理标志位,以及在一些位级编码场景下进行数据处理。

左移和右移运算符用于将二进制位向左或向右移动指定的位数,从而实现对数值的快速操作。左移操作将数值的二进制表示向左移动,等效于乘以2的幂次方,而右移操作将数值的二进制表示向右移动,等效于除以2的幂次方。这些运算符在处理大数据集、位掩码、网络协议以及嵌入式系统等领域都具有广泛的应用。

然而,需要注意的是,位操作并不常见于一般的业务逻辑编程,而更多地出现在需要对二进制数据进行处理的底层系统级编程中。在使用位操作时,应该清晰地理解位操作的语义,防止出现意外错误。同时,要考虑到可读性和代码维护性,不应滥用位操作,而是在合适的场景下使用,以提高代码的效率和性能。

二、Java的左移、右移运算符

  • << 是左移;如:<<1就是左移一位;<<2就是左移两位
  • >>”是右移;如:>>1就是右移一位;>>2就是右移两位

记忆技巧: 尖括号的方向朝向哪就是哪移。

左移就是将目标转换为二进制后,从右向左移动一位,右边补零,左边移除。
在这里插入图片描述

右移就是将目标转换为二进制后,从左向右移动一位,左边补零,右边移除。。
在这里插入图片描述

三、Java中左移、右移使用场景

可以代替乘(左移)和除(右移),如下:

package zd.hjd.test.synchronizedtest;

public class MyTestMain {
    public static void main(String[] args) {
        System.out.println(4*2);
        System.out.println(4<<1);
        System.out.println(4/2);
        System.out.println(4>>1);
    }
}

输出结果:

8
8
2
2

四、使用左移、右移优点和弊端

4.1 优点:

使用左移(<<)和右移(>>)的好处在于它们可以在某些情况下提供更高效的数值操作,特别是涉及到2的幂次方的操作。以下是一些使用左移右移的好处:

  1. 速度优势: 左移和右移操作是位级操作,它们在底层直接对二进制数据进行移动,相比于使用乘除法运算符,位移操作可以更快地完成数值的变换。这在一些需要高效计算的场景下尤为重要。
  2. 数值操作: 左移和右移可以用于实现数值的倍增或减少。例如,将一个数值左移n位,等效于将其乘以2的n次方;将一个数值右移n位,等效于将其除以2的n次方。
  3. 位掩码操作: 在位掩码操作中,可以使用左移来设置位,使用右移来读取位。这在一些标志位、开关状态的处理中非常有用。
  4. 位级编码: 在某些编码和解码场景下,需要将信息编码到特定的位上,或者从特定位上解码信息。左移和右移操作可以用于实现这种位级的数据处理。
  5. 嵌入式系统: 在嵌入式系统中,资源有限,效率至关重要。位移操作可以提供更紧凑和高效的代码,减少资源消耗。

4.2 弊端:

  1. 可读性下降: 左移和右移操作对于非熟悉位操作的开发者来说可能不太直观,代码的可读性可能会下降,使得代码难以理解和维护。
  2. 位移越界: 在使用右移操作时,如果对有符号的整数进行右移,可能会导致符号位扩展,从而改变数值的意义。例如,对于负数的右移可能会导致意外的结果。
  3. 移位溢出: 如果使用左移操作将某个位移到超出数据类型的范围,就会发生移位溢出,导致结果不正确。
  4. 代码依赖于底层实现: 使用位操作可能会使代码与底层硬件或编译器的实现相关,导致代码的可移植性下降。
  5. 复杂逻辑错误: 如果没有正确地处理边界情况,可能会导致复杂的逻辑错误,尤其是在涉及位级运算的复杂算法中。
  6. 难以维护: 过度使用位操作可能使代码变得难以理解和维护,特别是在逻辑复杂的情况下。
  7. 代码不易调试: 位操作可能会导致一些难以调试的问题,因为它们涉及底层位级表示,而不是更常见的数值操作。

五、使用左移、右移注意事项

  1. 带符号左移需要考虑移动后数字变为负数的情况,因为二进制的首位为符号位。
  2. 从上述中我们知道,左移就是将一个数字的二进制编码向左边移动,右边补零,右移相反。如果一个int类型的数字向左移32位结果是不是就是0呢?答案是错误的。当int类型数字进行左移,并且左移位数大于等于32位时,会先与32求余,然再进行移动。32%32 = 0,使用int类型向左移32位相当于不移动,byteshort类型同理。long类型是64位。
public class MoveLeft {
    public static void main(String[] args) {
       int a = 10;
        byte b = 50;
        short s = 60;
        System.out.println(a >> 1);// 5
        System.out.println(a << 1);// 20
        System.out.println(a << 32);// 10
        System.out.println(a << 33);// 20
        System.out.println(b << 32);// 50
        System.out.println(b << 33);// 100
        System.out.println(s << 32);// 60
        System.out.println(s << 33);// 120
        long longValue = 733183670L;
        System.out.println("longValue:" + (longValue));//打印longValue
        System.out.println("longValue左移1位:" + (longValue << 1));//左移1位
        System.out.println("longValue左移8位:" + (longValue << 8));//左移8位
        //当long类型左移位数大于等于64位操作时,会先求余后再进行移位操作
        System.out.println("longValue左移64位:" + (longValue << 64));//求余为64%64=0,相当于左移0位(不移位)
        System.out.println("longValue左移72位:" + (longValue << 72));//求余为72%64=8,相当于左移8位
        System.out.println("longValue左移128位:" + (longValue << 128));//求余为128%64=0,相当于左移0位(不移位)
    }
}
  1. double和float不能使用位移来操作,编译不通过。
    在这里插入图片描述

六、无符号右移>>>

无符号右移和右移原理一样,只不过是右移后在左边补零后舍弃掉符号位。如下所示:

public class MoveLeft {
    public static void main(String[] args) {
        int a = -10;
        System.out.println(a >>> 1);// 结果是 2147483643
    }
}

执行的过程如下:

//向得出-10的二进制,需要得到10的二进制
0000 0000 0000 0000 0000 0000 0000 ‭‭1010‬‬// 10 二进制如下
1111 1111 1111 1111 1111 1111 1111 0101// 10 的反码
1111 1111 1111 1111 1111 1111 1111 0110 //反码+1 就为 -10 的二进制
0111 1111 1111 1111 1111 1111 1111 1011// 右移一位
//转换为10进制 为 2147483643

记住Java中没有无符号左移。因为左移操作符 << 总是保持符号位,即使在移动过程中可能会导致符号位变为1。如果需要进行无符号左移操作,可以使用无符号右移操作 >>> 来实现。因为在大多数情况下,无符号左移和无符号右移的效果是一样的,都是向左或向右移动指定位数,只是填充的位不同。

七、Java中的其它特殊运算符

7.1 &

按位与运算
&是双目运算符。其功能是参与运算的两数各对应的二进制位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。

使用场景:

  • 位操作: 位运算符在底层数据处理和优化中很常见,例如对数据进行位掩码、位清除、位设置等操作。
  • 权限控制: 在权限控制中,可以使用位运算来对不同权限进行组合或判断。
  • 位集合: 将每个位视为一个标志,可以通过按位与运算来检查是否设置了特定的标志位。

例如,如果有一个整数 a 表示某个权限的掩码,另一个整数 b 表示用户的权限,通过 a & b 运算可以判断用户是否具有某个权限。

7.2 |

按位或运算
|是双目运算符。其功能是参与运算的两数各对应的二进制位相或。只要两数的二进制位中有一个是1,那么按位或的结果就是1;只有二进制两位都为0时,结果为0。

使用场景:

  • 位操作: 位运算符在底层数据处理和优化中很常见,例如对数据进行位标记、位组合等操作。
  • 权限控制: 在权限控制中,可以使用位运算来对不同权限进行组合或判断。
  • 位集合: 将每个位视为一个标志,可以通过按位或运算来设置特定的标志位。

例如,如果有一个整数 a 表示某个权限的掩码,另一个整数 b 表示用户的权限,通过 a | b 运算可以将用户的权限添加到掩码中。

7.3 ^

按位异或运算
~是双目运算符。其功能是参与运算的两数各对应的二进制位相异或。两个数字的二进制位相同则取0,不同值则取1。

异或运算符具有以下的性质:

(1)交换律:
(2)结合律:

(a^b)^c == a^(b^c)

(3)对于任何数X,都有:

x^x=0,x^0=x

(4)自反性

A XOR B XOR B = A xor 0 = A

使用场景:

异或运算最常见于多项式除法,不过它最重要的性质还是自反性A XOR B XOR B = A,即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。这是一个神奇的性质,利用这个性质,可以获得许多有趣的应用。

例如,大部分程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达式 (值) :

A=A XOR B (a XOR b) 
B=B XOR A (b XOR a XOR b = a)
A=A XOR B (a XOR b XOR a = b)
public class MyTestMain {
    public static void main(String[] args) {
        int a = 5;
        int b = 6;
        a = a^b;
        b = a^b;
        a = a^b;
        System.out.println("a:" + a);
        System.out.println("b:" + b);
    }
}

输出结果:

a:6
b:5

google的一个面试题:

一个数组存放若干整数,一个数出现奇数次,其余数均出现偶数次,找出这个出现奇数次的数?

上面的问题可以使用按位异或运算巧妙解决:

public class MyTestMain {
    public static void main(String[] args) {
        int[] nums = {2, 2, 3, 3, 4, 4, 5};
        int returnValue = 0;
        for (int num : nums) {
            returnValue ^= num;
        }
        System.out.println(returnValue);
    }
}

输出结果:

5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/905837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS自学框架之动画

这一节&#xff0c;自学CSS动画。主要学习了淡入淡出、淡入缩放、缩放、移动、旋转动画效果。先看一下成果。 优雅的过渡动画&#xff0c;为你的页面添加另一份趣味&#xff01; 在你的选择器里插入 animation 属性&#xff0c;并添加框架内置的 keyframes 即可实现&#xff0…

Typescript基础知识(类型拓宽、类型缩小)

系列文章目录 引入一&#xff1a;Typescript基础引入&#xff08;基础类型、元组、枚举&#xff09; 引入二&#xff1a;Typescript面向对象引入&#xff08;接口、类、多态、重写、抽象类、访问修饰符&#xff09; 第一章&#xff1a;Typescript基础知识&#xff08;Typescri…

Linux 线程同步——信号量、互斥锁、读写锁

一、线程同步的概念 这里的同步就是对程序的执行进行控制&#xff0c;因为如果不进行控制就会出现错误的问题&#xff0c;这里的控制是为了保证程序的正确性。 线程同步指的是当一个线程在对某个临界资源进行操作时&#xff0c;其他线程都不可以对这个资源进行操作&#xff0…

自然语言处理: 第九章DeepSpeed的实践

理论基础 仓库链接: microsoft/DeepSpeed: DeepSpeed is a deep learning optimization library that makes distributed training and inference easy, efficient, and effective. DeepSpees正如它官网介绍的一样&#xff0c;它为深度学习模型提供了一站式的快速以及大规模…

【SA8295P 源码分析】03 - SA8295P QNX Host上电开机流程分析

【SA8295P 源码分析】03 - SA8295P QNX Host上电开机流程分析 一、阶段1 固件开机自检 (SM BIST)&#xff1a;APPS PBL加载XBL后触发 INT_RESET进行Warm Reset二、阶段2 固件开机自检 (SM BIST)&#xff1a;加载TZ&#xff0c;初始Hypervisor&#xff0c;启动QNX Kernel&#x…

k8编写yaml文件小工具

在刚接触k8s的时候觉得yaml资源文件非常的难写&#xff0c;完全看不懂&#xff0c;经过一段时间的摸索学习&#xff0c;发现k8s平台中是提供了一系列的工具和技巧的&#xff0c;可以帮助我们很好的编写资源文件&#xff0c;提升编写yaml文件的能力&#xff0c;常用的命令工具是…

python爬虫9:实战2

python爬虫9&#xff1a;实战2 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…

时序预测 | MATLAB实现SO-CNN-LSTM蛇群算法优化卷积长短期记忆神经网络时间序列预测

时序预测 | MATLAB实现SO-CNN-LSTM蛇群算法优化卷积长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现SO-CNN-LSTM蛇群算法优化卷积长短期记忆神经网络时间序列预测预测效果基本介绍程序设计学习总结参考资料 预测效果 基本介绍 时序预测 | MATLAB实现SO-CNN-LSTM蛇群…

深入解析淘宝API,实现高效商务应用

淘宝API的基本调用 1. API文档与SDK 淘宝API官方提供了详细的API文档&#xff0c;包含了API的使用说明、参数列表、示例代码等内容。开发者可以通过文档了解每个API接口的具体功能和使用方法。此外&#xff0c;淘宝API还提供了多种编程语言的SDK&#xff0c;方便开发者进行快速…

桌游新篇:3.1 UserCase分析

距离上一次停止更新这个系列有将近9个月了。 工作这么久&#xff0c;学会了一件事&#xff0c;就是想清楚再动手。当然&#xff0c;后续工作已经渐渐展开了&#xff0c;而且当下属于天时地利人和&#xff08;既有当前MR设备带来的硬件buff&#xff0c;又有大语言模型&#xff…

SOPC之NIOS Ⅱ实现电机转速PID控制

通过FPGA开发板上的NIOS Ⅱ搭建电机控制的硬件平台&#xff0c;包括电机正反转、编码器的读取&#xff0c;再通过软件部分实现PID算法对电机速度进行控制&#xff0c;使其能够渐近设定的编码器目标值。 一、PID算法 PID算法&#xff08;Proportional-Integral-Derivative Algo…

21-注意点说明:scoped样式冲突 / data

组件的三大组成部分 - 注意点说明 组件的样式冲突 scoped 默认情况:写在组件中的样式会 全局生效 -> 因此很容易造成多个组件之间的样式冲突问题 1.全局样式: 默认组件中的样式会作用到全局 2.局部样式: 可以给组件加上 scoped 属性,可以让样式只作用于当前组件 scoped原理…

《有效调节情绪,保持工作心态平和》

工作中&#xff0c;我们有时会遇到各种挑战和困难&#xff0c;这些挑战和困难可能引发我们的负面情绪&#xff0c;例如焦虑、愤怒和沮丧等。然而&#xff0c;保持稳定的情绪是实现高效工作的重要因素之一。本文将分享如何在工作中保持稳定的情绪。 首先&#xff0c;让我们来谈谈…

Spring Boot 如何通过jdbc+HikariDataSource 完成对Mysql 操作

&#x1f600;前言 本篇博文是关于Spring Boot 如何通过jdbcHikariDataSource 完成对Mysql 操作的说明&#xff0c;希望你能够喜欢&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的…

Python多组数据三维绘图系统

文章目录 增添和删除坐标数据更改绘图逻辑源代码 Python绘图系统&#xff1a; 基础&#xff1a;将matplotlib嵌入到tkinter &#x1f4c8;简单的绘图系统 &#x1f4c8;数据导入&#x1f4c8;三维绘图系统自定义控件&#xff1a;坐标设置控件&#x1f4c9;坐标列表控件 增添和…

录屏有哪些讲究?有哪些好用的录屏软件?

在如今数字时代&#xff0c;视频分享已经成为一种流行的传播方式。为了制作高质量的视频内容&#xff0c;录屏已经成为了一种必备的技能。但是&#xff0c;要想制作出令人满意的录屏视频&#xff0c;需要了解一些讲究和使用一些好用的录屏软件。 录屏是一种视觉传达方式&#x…

【prism】发布订阅和取消订阅,进一步梳理

一个对象对应一个事件订阅 一个事件是可以被重复订阅的,如果一个事件被订阅了三次,那边发布一次该事件,就会触发三次事件订阅: 通过观察Prism的事件聚合器对象,发现它此时包含了三个事件对象,其中第三个事件订阅数量达到了3! 这样的话,如果调用一次 Publish ,那么S…

Android 获取 SHA256 签名

在 Android Studio 中的 Terminal &#xff0c;输入命令: keytool -list -v -keystore debug.keystore 如果出现以下提示&#xff1a; keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -keyalg RSA -validity 10000 按照提示输入相关信息&#xff0c;…

SIP 7英寸触摸屏寻呼主机

SV-8006TP SIP7英寸触摸屏寻呼主机 一、描述 SV-8006TP是我司的一款SIP桌面式对讲广播主机&#xff0c;具有10/100M以太网接口&#xff0c;从网络接口接收网络的音频数据&#xff0c;提供立体声音频输出。 SV-8006TP寻呼话筒可以通过麦克风或者本地线路输入对终端进行分区广…

Java【手撕双指针】LeetCode 283. “移动零“, 图文详解思路分析 + 代码

文章目录 前言一、移动零1, 题目2, 思路分析3, 代码展示 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结构: 顺序表, 链表,…