原码、反码、补码以及java位运算(转载)
转载自:https://www.cnblogs.com/findbetterme/p/10787118.html (若有冒犯,评论立删)
一、前言
在计算机二进制中bit(位 简称b或比特)是数据存储的最小单元,每个二进制数由0或1组成,每一个数字就是一位bit,其中每8bit = 1 byte(字节)
java中的基本数据类型
| 数据类型 | 所占字节数 | 所占位数 |
|---|---|---|
| byte | 1 byte | 8 bit |
| short | 2 byte | 16 bit |
| int | 4 byte | 32 bit |
| long | 8 byte | 64 bit |
| float | 4 byte | 32 bit |
| double | 8 byte | 64 bit |
二、符合位
二进制数最高位为符合位,整数又分为正数和负数,正数为无符号位(最高位为0),负数为有符合位(最高位位1)
譬如:
5 ---> 二进制数:00000000 00000000 00000000 00000101
-5 ---> 二进制数:10000000 00000000 00000000 00000101
三、原码、反码、补码
3.1 原码
原码就是该数字不进行其他操作,数字最原始的二进制表示,在java中,对于整数而言,其原码格式为最高位为符号位,该位上1表示负数,0表示正数,剩余位数为该数字的二进制表示
对于原码取绝对值,只有符号位发生改变,其他位不变(若符号位为1,取绝对值后为0)
3.2 反码
正数的反码:正数原码
负数的反码:负数原码除符号位以外的位数取反(若为0则改为1,若为1则改为0)
3.3 补码
正数的补码:正数原码
负数的补码:负数反码后加1(-b = ~b + 1)
负数补码转原码:补码减一再取反
注意:
- 计算机运算的时候,都是以补码的方式来运算
- 二进制转换十进制,必须使用二进制的原码进行转换
四、思考:java中为什么byte的取值范围是-128~127
java中byte占一个字节, 也就是8bit(位), 其中最高位是符号位, 剩下7位用来表示数值。
若符号位为0, 则表示为正数,范围为00000000~01111111(补码形式),也就是十进制的0-127. 若符号位为1, 则表示为负数, 范围为10000000~11111111(补码形式), -128~-1, 11111111转换为原码就是10000001,也就是-1。
在补码中,为了避免存在"-0",规定10000000为-128, 所以解释了byte的取值范围为什么是-128~127。
五、位运算符
5.1 & 按位与
规则:两个数的二进制数中,只有两个数对应的二进制位数同为1时,结果为1,反之为0,对应位数同为0时,结果为0,反之为1



5.2 | 按位或
规则:两个数的二进制数中,只有两个数对应的二进制位数同为0时,结果为0,对应的位数同为1时,结果为1,其余结果都为1
5.3 ~ 按位非
规则:单目运算符,该数值的二进制数除符号位以外都取反
正数取反为负数,比原值小1 负数取反为整数,比原值小1 可以用该特征求绝对值
5.4 ^ 按位异或
规则:两个数的二进制数中,只有两个数对应的二进制位数相同时(同为1或0),结果为1,否则其余结果都为0
5.5 << 左位移
规则:数值的二进制位数向左移动,符号位不变,低位补0;如:2<<2结果为8

当移动的位数超过数字本身的位数时,那么不就都需要补0操作,实际上不是的,java不可能做那么浪费资源的事情。在真正执行位移前,其对要移动的位数做了一些预处理,比如32处理为0,-1处理为31
左移几位,相当于乘与2的几次幂
5.6 >> 右位移
规则:数值的二进制位数向右移动,如果该数为正数,则高位补0,若为负数,则高位补1;如:-6>>2结果为-2

右移几位,相当于除以2的几次幂
5.7 >>> 无符号右移
规则:数值的二进制位数向右移动,也叫逻辑右移,即若该数为正,则高位补0,若该数为负数,则右移后高位同样补0(注意,无符号右移(>>>)中的符号位(最高位)也跟着变,无符号的意思是将符号位当作数字位看待)

浙公网安备 33010602011771号