首页 > 编程语言 >Java的7种位运算符

Java的7种位运算符

时间:2023-06-20 21:46:46浏览次数:63  
标签:Java 种位 System 取反 运算符 ----- println out

位运算符

在Java语言中,提供了7种位运算符,分别是按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)、带符号右移(>>)和无符号右移(>>>)

操作符 语义 描述 运算规则
&    按位与      二进制数据按位与操作 如果两个二进制位上的数都是1,那么运算结果为1,其他情况运算结果均为0。 (0&0=0 1&1=1 1&0=0 0&1=0)
|    按位或      二进制数据按位或操作 两个二进制位上的数字如果都为0,那么运算结果为0,否则运算结果是1。(0|0=0 0|1=1 1|0=1 1|1=1)
~    按位取反      二进制数据按位取反 对每个二进制位进行取反操作,所谓取反就是原来二进制位上如果是0,那么就变成1,反之,如果原来二进制位上是1,那么就变为0。即:取反就是1为0,0为1。取反运算符是一个单目运算符,所以只需要一个操作数就可以了。
^    按位异或      二进制数据异或,相同为假、不同为真 两个二进制位上的数字如果相同,则运算结果为0;如果两个二进制位上的数字不相同,则运算结果为1。(1^0 = 1 , 1^1 = 0 , 0^1 = 1 , 0^0 = 0)
>>    右移      二进制数据整体右移 各二进位全部右移若干位,对无符号数,高位补0;有符号数,各编译器处理方法不一样,有的补符号位(算数右移),有的补0(逻辑右移),(相当于除2)左边补符号位
<<    左移      二进制数据整体左移 各二进位全部左移若干位,高位丢弃,低位补0,(相当于乘2)右边补0
>>>    无符号右移      二进制数据整体右移,符号位补0 (相当于除2)左边补0

注意事项

  1. 运算符当中,仅有~是单目运算符,其他运算符均为双目运算符。【就是运算符操作数的个数,单目就是一个操作数,双目就是两个操作数】
  2. 位运算符是对long、int、short、byte和char这5种类型的数据进行运算的,不能对double、float和boolean进行位运算操作。
  3. 凡是位运算符,都是把值先转换成二进制,再进行后续的处理。
  4. 按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整型值。
  5. 对数值类型数据进行按位操作;1表示true、0表示false。
  6. 位移操作同取反操作一样,并不能改变变量本身的值,所能改变的仅是存储在操作数栈中那个数据的值.【即定义一个变量i并赋值,对i取反后i的值不发生改变】
  7. 当位移的位数很多时,导致最左边的符号位发生变化,就不再具有乘以2的N次方的效果了。比如十进制的5转换为补码形式是:前面29个0最后3位是101,如果移动29位,那么最前面的符号位就变成了1,此时运算的结果就成为了一个负数,不再是5乘以2的29次方的乘法结果。
  8. 如果位移数超过31,则虚拟机会对位移数按连续减去32,直到得到一个小于32并且大于等于0的数,然后以这个数作为最终的位移数。例如:对int型变量进行位移97位的操作,虚拟机会首先对97连续减去3个32,最终得到数字1,实际进行位移运算时只对变量位移1位。而对于long类型的数据而言,最多支持63位的位移运算,如果位移数超过63,则连续减去64,以最终得到的小于64并且大于等于0的数作为位移数。
  9. 带符号右移的操作可以保证移动之前和移动之后数字的正负属性不变,原来是正数,不管移动多少位,移动之后还是正数,原来是负数,移动之后还是负数。
  10. 对于任何一个byte、short或者int类型的数据而言,带符号右移31位之后,得到的必然是0或者是-1。对于long类型的数据而言,带符号右移63位之后,得到的也必然是0或者是-1。

关于原码、反码、补码

  1. 二进制的最高位是符号位:0表示整数,1表示负数
  2. 正数的原码、补码、反码都一样(三码合一)
  3. 负数的反码=它的符号位不变,其它位取反(0->1,1->0)
  4. 负数的补码=它的反码+1,负数的反码=负数的补码-1
  5. 0的反码,补码都是0
  6. java没有无符号数
  7. 在计算机运算的时候,都是以补码的方式运算
  8. 当我们看运算结果的时候,要看他的原码

常见用法

package com.javacore;

public class Demo {

	public static void main(String[] args) {
		System.out.println("-----按位与运算符-----");
		/**
		 * 按位与运算符
		 * 
		 * 00000000000000000000000000000001
		 * 00000000000000000000000000000010
		 * --------------------------------
		 * 00000000000000000000000000000000
		 * 
		 */
		System.out.println("1&2 = " + (1&2)); 
		
		System.out.println("-----按位或运算符-----");
		/**
		 * 按位或运算符
		 * 
		 * 00000000000000000000000000000001
		 * 00000000000000000000000000000010
		 * --------------------------------
		 * 00000000000000000000000000000011
		 * 
		 */
		System.out.println("1|2 = " + (1|2)); 
		
		System.out.println("-----取反运算符-----");
		/**
		 * 取反运算符
		 * 
		 * 正数取反【正数原码、反码、补码一样】
		 * -> 1的原码  00000000000000000000000000000001
		 * -> 1的补码  00000000000000000000000000000001
		 * -> 按位取反 11111111111111111111111111111110 【结果的补码】
		 * -> 结果补码的反码 10000000000000000000000000000001【负数最高位不变,其余取反】
		 * -> 结果反码加1得到补码的补码即为结果的原码 10000000000000000000000000000010
		 * 
		 * 负数取反
		 * -> -1的原码 10000000000000000000000000000001
		 * -> -1的反码 11111111111111111111111111111110
		 * -> -1的补码 11111111111111111111111111111111【反码加1】
		 * -> 对-1补码按位取反 00000000000000000000000000000000【结果的补码】
		 * -> 正数三码合一,所以结果即为 00000000000000000000000000000000
		 */
		System.out.println("~1 = " + (~1)); 
		System.out.println("~-1 = " + (~-1)); 
		
		System.out.println("-----异或运算符-----");
		/**
		 * 异或运算符
		 * 
		 * 00000000000000000000000000000001
		 * 00000000000000000000000000000010
		 * --------------------------------
		 * 00000000000000000000000000000011
		 */
		System.out.println("1^2 = " + (1^2)); 
		
		////面试题:不使用第三个变量交换两个数字
		swap(10,20);
		
		System.out.println("-----左移运算符-----");
		/**
		 * 左移运算符
		 */
		int a = 7;
		System.out.println("a<<2:" + (a<<2)); 
		System.out.println("-7<<2:" + (-7<<2)); 
		System.out.println("a<<30:" + (a<<30)); 
		System.out.println("a:" + a); 
		
		System.out.println("-----右移运算符-----");
		/**
		 * 右移运算符
		 */
		int b = 9;
		System.out.println("b>>2:" + (b>>2)); 
		System.out.println("-9>>2:" + (-9>>2)); 
		System.out.println("b>>30:" + (b>>30)); 
		System.out.println("-9>>30:" + (-9>>30));
		System.out.println("b:" + b); 
		
		System.out.println("-----无符号右移运算符-----");
		/**
		 * 无符号右移运算符
		 */
		System.out.println("20>>>2:" + (20>>>2)); 
		System.out.println("-20>>>2:" + (-20>>>2)); 
		
		System.out.println("-----判断奇偶数-----");
		/**
		 * 判断奇偶数:该数二进制的最后一位是0的话那么就为偶数;是1的话就为奇数
		 */
		for (int i = 0; i < 10; i++) {
			System.out.println(1 == (1&i) ? (i + "是奇数") : i + "是偶数");
		}
		
		System.out.println("-----改变正负性-----");
		/**
		 * 正数变成负数,负数变成正数
		 */
		System.out.println(~11 + 1);
		System.out.println(~-11 + 1);
		
		System.out.println("-----求绝对值(一)-----");
		/**
		 * 负数变成正数,正数不变
		 */
		int i = 6 >> 29;
		int j = -6 >> 29;
		System.out.println(i == 0 ? 6 : (~6 + 1));
		System.out.println(j == 0 ? -6 : (~-6 + 1));
		
		System.out.println("-----求绝对值(二)-----");
		/**
		 * 负数变成正数,正数不变
		 */
		int m = 6 >> 29;
		int n = -6 >> 29;
		System.out.println((6 ^ m) - m);
		System.out.println((-6 ^ n) - n);
	}
	
	/**
	 * 不使用第三个变量交换两个数字
	 * @param x
	 * @param y
	 */
	public static void swap(int x, int y) {
		System.out.println("交换前 x = " + x + " y = " + y);
        //加减法;缺点,如果数据大可能会出现溢出
        //x=x+y;
        //y=x-y;
        //x=x-y;
        //异或法
        x=x^y;
        y=x^y;
        x=x^y;
        System.out.println("交换后 x = " + x + " y = " + y);
	}

}

结果:
-----按位与运算符-----
1&2 = 0
-----按位或运算符-----
1|2 = 3
-----取反运算符-----
~1 = -2
~-1 = 0
-----异或运算符-----
1^2 = 3
交换前 x = 10 y = 20
交换后 x = 20 y = 10
-----左移运算符-----
a<<2:28
-7<<2:-28
a<<30:-1073741824
a:7
-----右移运算符-----
b>>2:2
-9>>2:-3
b>>30:0
-9>>30:-1
b:9
-----无符号右移运算符-----
20>>>2:5
-20>>>2:1073741819
-----判断奇偶数-----
0是偶数
1是奇数
2是偶数
3是奇数
4是偶数
5是奇数
6是偶数
7是奇数
8是偶数
9是奇数
-----改变正负性-----
-11
11
-----求绝对值(一)-----
6
6
-----求绝对值(二)-----
6
6

转载自:
https://blog.csdn.net/yinying293/article/details/128481204
https://blog.csdn.net/weixin_65584018/article/details/126931663
https://mp.weixin.qq.com/s?__biz=MzI0OTQwNDQxMw==&mid=2247483760&idx=1&sn=27cbdd41da43b5b71c9f7a3ae807fae6&chksm=e9934fe2dee4c6f4869f6d46004c2f3a76c3b5aefc1d1acc8acd9504c64e9a8143f21fe2c968&scene=27

标签:Java,种位,System,取反,运算符,-----,println,out
From: https://www.cnblogs.com/mn609/p/17494904.html

相关文章

  • 基于JAVA文件管理系统的设计与实现
    文件管理系统实现了文件浏览、文件分类、文件上传的功能需求,该系统是文件批处理处理过程中的重要组成部分,可实现文件信息的正确性、实时性、全面性、快捷性等需求。这个系统是基于Windows操作系统下,基于J2EE采用了Jsp、spring mvc、网络编码等技术,与MYSQL数据库管理系统来结......
  • 使用poi时报错:java.io.EOFException: Unexpected end of ZLIB input stream
    原文:点击查看代码FileexcelFile=newFile(filePath);try{if(excelFile.exists()){wb=newSXSSFWorkbook(newXSSFWorkbook(excelFile),1000,true);}else{wb=newSXSSFWorkbook(1000);}}catch(IOExceptione){logger.error(tra......
  • Java中的String、StringBuilder和StringBuffer
    StringString为什么不可变?有什么好处?在Java中的String源码中,我们可以看到字符串String类就是char数组的封装,且字符char[]前面的修饰关键字是private和final。final决定了char数组是私有成员变量,不可以指向新的数组。private决定了该数组只能有String类内部访问,所以不可变。好......
  • 后台导出excel报错,java.io.IOException:Permission denied
    java使用poi导出excel,会创建并使用一个临时文件夹这个问题的原因就是临时文件夹的操作权限不够,使用chown修改文件夹权限即可。linux中临时目录是/tmp/poifileswindow是在AppData\Local\Temp\poifiles......
  • Java集合
    java有什么集合?集合的概念:用于存储数据的数据类统称为集合。java的集合可以分两种,Collection和Map。它们都是java集合框架的接口。Collection表示一组对象的集合。常用实现类:ListList是一种有序可重复的集合,常见的List实现类有ArrayList和LinkedList。ArrayList和Linke......
  • Java类属性第二个字母大写问题,请求参数设置不上,返回参数小写
     其实这个问题几年前就遇到过,也解决了,但是最近又看到项目中有人这么用,就想起来了,写在这里,给自己也给大家提个醒。在Java中,如果类的某个属性第二个字母是大写,比如:nToken,这样的属性一定要自己手动生成getter和setter方法。如果使用lombok的@Data注解,它默认生成的getter和setter......
  • js加密与java解密的RSA(公钥/私钥)算法
    前言:公司用的加密算法是对称密钥加密算法,服务器上的公钥与客户端的私钥都是相同的,如果不小心泄露或者通过反编译软件把客户端重新编译就会泄露密钥,这样加密后的数据就不安全了。商量使用非对称密钥RSA来解决这种问题,非对称密钥分为公钥和私钥,公钥可以公开给客户端分发给所有......
  • daka:p java
    终于搞定eclipse了用eclipse编译输出“helloworld!” 感觉比之前方便了许多,终于不用cmd了学习了一下Java的基础语法,感觉在数据类型上与C并没有太大的差异。 ......
  • Java GUI 体系
    类别基于Java的图形库最主要的有三种,它们分别是:AWT:抽象窗口工具包Swing:基于对AWT进行的改进而诞生的组件库SWT/JFace:IBM在研发Eclipse平台而退出的组件库起源在早期JDK1.0发布时,Sun公司就为GUI开发提供了一套基础类库,这套类库被称为AWT(AbstractWindow......
  • JavaScript(05): 正则表达式
    当检索某个文本的时候,我们可能需要一种模式来描述被检索的内容,在这种情况下就可以考虑使用正则表达式。正则表达式可以定义一种模式,这种模式可能是一个简单的字符、也可能是一个非常复杂的字符串,通常被用于解析、格式检查、替换等。关于正则表达式的具体内容可以参考以下链接,本文只......