天天看点

Java位运算之异或运算,非运算,与运算,或运算,移位运算

java语言对应数学中逻辑运算

"∧" 表示 "与" 对应java : &

"∨" 表示 "或" 对应java : |

"┐"表示 "非" 对应java : ~

a⊕b = (¬a ∧ b) ∨ (a ∧¬b) 异或(xor) 对应java : ^

在计算机中,数值一直以补码存储,运算也用补码。

ex:8bit signed int (-128~127),最高位为符号位,0000 0000 ~ 1111 1111 以补码形式存储 带符号数

0000 0000 :十进制0 1+(-1)=0,其实用的是1的补码和-1的补码相加。正数的补码为本身

0000 0001 :1(0+1) 即0000s 00001+?= 0000 0000 当?为1111 1111 时相加为1 0000 0000 最高位进位被舍弃

.... 由此诞生了-1在计算机中存储的二进制 1111 1111,即-1的补码

0111 1111 : 127 所有从 1~127 都有对应的-1~-127,一个数的补码+该数相反数的补码 = 0(1 0000 0000)

1000 0000 : -128 多出了 0000 0000 (0的补码)和 1000 0000 (-128的补码)

....

1111 1111 : -1 从-128(1000 0000)+1.... -1(11111 1111))+1 = 0 (0000 0000) +1.... 127 (0111 111)

验证计算机只会做加法,且带符号位(8 bit)整型范围(-128 ~127)

同时可以证明 负数的补码=相反数的补码按位取反+1

正数原码=补码=反码,涉及负数才有补码反码之间计算

原码:1010(-2)

补码:1110

补码 = (原码)按位取反+1(原码除符号位按位取反+1)

在位运算中计算得知补码后怎么转换为直观的原码

原码 = (补码 -1)后除符号位按位取反

原码 = 反码(补码除符号位取反) +1

Java中没有无符号数据类型,取最高位作为符号位表示正负数,但运算和位操作都使用补码计算

与运算 &  规则 :对应数的补码对应位都为1时结果位才为1

System.out.println( 7 & 9);//result为1

分析:

7的二进制:0111(即为源码也为补码)

9的二进制:1001

result :0001

System.out.println(-1&-2); //输出-2

分析:

-1原码:1001 对应补码:1111

-2原码:1010 对应补码:1110

result: 得到补码:1110(即负数补码,-2的补码)

1101 补码-1 或 1001 除符号位按位取反得反码

1010 按位取反得原码,即带符号的-2 1010 反码+1得原码 -2

同理或运算,异或运算,取反运算相同,都为对补码行运算

输出结果

或运算 | 规则:有一个位为1,则结果位为1

 System.out.println(7 | 9);// 15

分析:

7的二进制:0111

9的二进制:1001

result :1111

异或运算  ^ 规则:对补码不同位不同为1 

System.out.println( 7 & 9);//result为14//System.out.println((~7&9)|(7&~9));//结果相同

分析:

7的二进制:0111

9的二进制:1001

result :1110

取反运算 ~ 规则:对补码按位取反

System.out.println( ~7);//输出-8

分析:

7的二进制:0000 0000 0000 0000 0000 0000 0000 0111

正整数的原码=补码,然后对补码求反

result: 1111 1111 1111 1111 1111 1111 1111 1000  //符号位改变(第一位),取反之后变成负数了(即负数的补码)

1000 0000 0000 0000 0000 0000 0000 0111 //反码(除符号位取反)

1000 0000 0000 0000 0000 0000 0000 1000 //对反码+1(得原码)== -8

System.out.println( ~-7);//输出6

分析:

-7的二进制:1000 0000 0000 0000 0000 0000 0000 0111 //该为原码,计算机中存储,计算的为补码,需转换为补码再按位求反

result: 1111 1111 1111 1111 1111 1111 1111 1001  //补码

0000 0000 0000 0000 0000 0000 0000 0110 //对补码求反仍然为补码

// 但符号位为0 即正数,补码=原码  == 6

移位运算 << (有符号左移), >>(有符号右移) , >>>(无符号右移)

<< :左移后,低位补0

>> :右移后,正数高位补0,负数高位补1

>>> :无符号右移,高位都补0

a << n  左移n位,值为a*2^n

a >> n  右移n位,值为a/2^n

继续阅读