反码、原码、补码及位运算
JAVA的基本数据类型及其取值范围
类型 | 存储需求 | bit 数 | 取值范围 | 备注 |
---|---|---|---|---|
int | 4字节 | 4*8 | -2147483648~2147483647 | 即 (-2)的31次方 ~ (2的31次方) - 1 |
short | 2字节 | 2*8 | -32768~32767 | 即 (-2)的15次方 ~ (2的15次方) - 1 |
long | 8字节 | 8*8 | 即 (-2)的63次方 ~ (2的63次方) - 1 | |
byte | 1字节 | 1*8 | -128~127 | 即 (-2)的7次方 ~ (2的7次方) - 1 |
float | 4字节 | 4*8 | float 类型的数值有一个后缀 F(例如:3.14F) | |
double | 8字节 | 8*8 | 没有后缀 F 的浮点数值(例如:3.14)默认为 double | |
boolean | 1字节 | 1*8 | true、false | |
char | 2字节 | 2*8 | Java中,只要是字符,不管是数字还是英文还是汉字,都占两个字节。 |
反码、原码、补码
在计算机系统中,数字一律用补码来表示、运算和存储。
原码:最高位为符号位的二进制数。
反码:正数的反码是其本身,负数的反码在其原码的基础上,符号位不变,其余各个位取反。
补码:正数的补码是其本身,负数的补码在其原码的基础上,符号位不变,其余各位取反,最后+1。
由来:
本来的二进制数是没有正负的,为了区分正负数,将二进制的最高位用来表示正负(0表示正,1表示负),所以有了原码。
但是原码表示正负数时,相反数相加不等于零,故产生了反码。
反码的出现解决了相反数相加不等于零的情况,但是在反码中有两个0(即+0和-0),为了解决这个问题出现了补码。
补码在反码的基础上+1,丢掉最高位,此时就解决了存在-0的问题,在失去了-0的同是得到了一个-8。
在补码转十进制时,实际上去除第一位符号位,0代表1,1代表0。
JAVA中基础类型的取值范围如何得到
由反码、补码、原码的关系可以很容易的知道每个基本类型的取值范围。
位运算
左移 <<: 丢弃左边指定位数,右边补0。
int值左移超过32位时(包括32),先对移动的位数与32进行求余(%),例如:32%32=0,相当于不移位;40%32=8,相当于左移8位。如果时long值,求余基数未64。
int intValue = 733183670;//随意写一个数
System.out.println("intValue:" + (intValue));//打印intValue
System.out.println("intValue左移1位:" + (intValue << 1));//左移1位
System.out.println("intValue左移8位:" + (intValue << 8));//左移8位
//当int类型左移位数大于等于32位操作时,会先求余后再进行移位操作
System.out.println("intValue左移32位:" + (intValue << 32));//求余为32%32=0,相当于左移0位(不移位)
System.out.println("intValue左移40位:" + (intValue << 40));//求余为40%32=8,相当于左移8位
System.out.println("intValue左移64位:" + (intValue << 64));//求余为64%32=0,相当于左移0位(不移位)
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位(不移位)
其中double
和float
在二进制中的表现比较特殊,因此不能来进行移位操作,报错,编译不过 。
其他几种整型byte
、short
移位前会先转换为int类型(32位)再进行移位。
右移 >> :丢弃右边指定位数,左边补上符号位。
和左移一样,int类型移位大于等于32位时,long类型大于等于64位时,会先做求余处理再位移处理,byte,short移位前会先转换为int类型(32位)再进行移位。
无符号右移 >>>: 丢弃右边指定位数,左边补上0。
无符号右移运算符和右移运算符是一样的,不过无符号右移运算符在右移的时候是补0的,而右移运算符是补 符号位的。
与运算&
两个位都是 1 时,结果才为 1,否则为 0 。如:
1 0 0 1 1
& 1 1 0 0 1
---------
1 0 0 0 1
或运算|
两个位都是 0 时,结果才为 0,否则为 1,如 :
1 0 0 1 1
| 1 1 0 0 1
----------
1 1 0 1 1
异或运算^
两个位相同则为 0,不同则为 1,如:
1 0 0 1 1
^ 1 1 0 0 1
-----------
0 1 0 1 0
取反运算~
- 0 则变为 1,1 则变为 0,如 :
- 1 0 0 1 1
-----------
0 1 1 0 0