Java 移位、逻辑运算符详解(~史上最全|吹牛逼)

目录

一、<< :左移运算符

二、>> :右移运算符

三、>>> :无符号右移

四、& :与运算

五、| :或运算

六、~ :非运算 

七、^ :异或运算

拓展问题:

一:从计算速度上讲,移位运算要比算术运算快?

二:二进制的起源

日常发车:


参考文章:
https://blog.csdn.net/is_zhoufeng/article/details/8112199

一、<< :左移运算符

说明:将运算符左边的对象向左移动运算符右边指定的位数(在低位补0)
通俗含义:num << 1,相当于num乘以2,依次数字递增,乘以2的平方(不严谨)

例如:

2 << 1 //4 移了一位2*2

2 << 2 //8 移了两位 2*2*2

2 << 3 //16 移了三位 2*2*2*2

 

二、>> :右移运算符


说明:如果值为正,则在高位补0,如果值为负,则在高位补1.
通俗含义:num >> 1,相当于num除以2,依次数字递增,除以2的平方(不严谨)

例如:

16 >> 1 //8 移了一位 16/2

16 >> 2 //4 移了两位 16/2/2

16 >> 3 //2 移了三位 16/2/2/2


三、>>> :无符号右移


说明:忽略符号位,高位都以0补齐
含义:无符号右移运算符>>>  结果总是正数或者0 

为什么只对正数有意义,对负数没有什么算术意义,只有逻辑意义:
因为如果一个数位负数,按照现实中数学常识,除以或乘一个负数都是负数,但在程序中都是正数显示

为什么只是对32位和64位的值有意义 ?
例如:

System.out.println(-1024 >> 4); //-64

System.out.println(-1024 >>> 4); //268435392

System.out.println(1024 >>> 24); //0


引申:
与(&)、非(~)、或(|)、 从电路的角度理解 

“门”是这样的一种电路:它规定各个输入信号之间满足某种逻辑关系时,才有信号输出。
从逻辑关系看,门电路的输入端或输出端只有两种状态,无信号以“0”表示,有信号以“1”表示。

产生:通常有下列三种门电路:与门、或门、非门(反相器)

0为假,1为真     =====》
true ——> 1
false ——> 0

四、& :与运算

说明;符号两边都为true,结果才是true,否则为false;对于数字,可将数字转换为2进制形式去理解,采用同位 与 操作即可得出结果。
联想:在与运算中两个开关是串联的,如果我们要开灯,需要两个开关都打开灯才会打开。

例如:

true&true=true

true&false=false

false&false=false

2&3=2 即:0010&0011=0010 (从高位到低位,依次做与操作)

五、| :或运算

说明:符号两边只有有一个为true,则结果为true,否则为false;对于数字,可将数字转换为2进制形式去理解,采用同位 或 操作即可得出结果。
联想:在或运算中两个开关是并联的,即一个开关开,则灯开。

例如:

true|true=true

true|false=true

false|true=true

false|false=false

2|3=3 即:0010|0011=0011 (从高位到低位,依次做或操作)


六、~ :非运算 


联想:非门输出与输入相反,即取反运算

例如:


!true=false

!false=true

System.out.println(~2);//-3

System.out.println(~-2);//1

七、^ :异或运算

说明:相同为0,不同为1;对于数字,可将数字转换为2进制形式去理解,采用同位 异或 操作即可得出结果。
含义:异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示,其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。

重要性质:
自反性:A XOR B XOR B = A xor  0 = A
即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身

不进位加法:如1+1=0,,0+0=0,1+0=1。

实际应用:
利用自反性,可以获得许多有趣的应用。 例如,所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有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)

 类似地,该运算还可以应用在加密,数据传输,校验等等许多领域。

常规测试:

2^3=1,即0010^0011=0001

true^true=false

false^false=false

true^false=true

5^2=7 即:0101^0010=0111 (从高位到低位,依次做异或操作)

 

拓展问题:

 

一:从计算速度上讲,移位运算要比算术运算快?


参考:https://blog.csdn.net/fyilun/article/details/45168253

CPU角度:
因为移位指令占2个机器周期,而乘除法指令占4个机器周期。

 

因为移位指令不需要涉及到逻辑运算.

常规一条指令被拆分的步骤
IF    ID    EX    MEM     WB UP
取指、译码、执行、访存、写回、更新

移位指令:取指 、写回(写)
乘除法指令:取指、译码、执行、写回(一次逻辑运算和一次写)

从硬件上看,移位对硬件更容易实现,所以会用移位,移一位就乘2,这种乘法当然考虑移位了。

实际应用角度,JVM的自主优化:
对于乘法和以及%运算,JVM一定会优化,这些是不需要程序员去考虑的,直接去用*/%即可。
对于除法,因为上述问题,确实是位移更快些。不过通常还是考虑使用位运算:
例如JVM源码:

java.util.Arrays.binarySearch:

int low = fromIndex;
int high = toIndex - 1;

while (low <= high) {
    int mid = (low + high) >>> 1;
    int midVal = a[mid];

    if (midVal < key)
        low = mid + 1;
    else if (midVal > key)
        high = mid - 1;
    else
        return mid; // key found
}
return -(low + 1);  // key not found.

解析:(low + high) >>> 1代替(low + high) /2是非常正确的,首先是因为数组下标肯定不会是负数,另一方面如果low + high大于int最大值(溢出变为负数了)时,只有>>>1能保证结果正确。

 

二:二进制的起源

中国的《易经》以爻、卦来表示天地和万物,其中爻是最基本的元素,爻分阴爻(用“--”表示)和阳爻(用“—”表示)两种,阴爻和阳爻的不同排列就是卦象,一个卦象称为一卦,一卦由六爻组成一卦就是一个整体。

世界万物中最基本的要素有8种,分别是天、地、雷、风、水、火、山和泽,他们分别用八卦表示,即乾、坤、震、坎、离、艮、兑,八卦互相搭配又得六十四卦,用来表示各种自然现象和人事现象。

我们对比二进制的组成:二进制的位用0,1表示,3位二进制可组合成8种状态,即可表示为0,1,...,7这8个数,而2个3位二进制组合,即变为6位二进制数,即:2=64,即64种状态。


莱布尼兹是第一个认识到二进制记数法重要性的人,并系统地提出了二进制数的运算法则。二进制对200多年后计算机的发展产生了深远的影响。他于1716年发表了《论中国的哲学》一文,
还设计了一台可以完成数码计算的机器。并进行了二进制的推广。

参考:
https://zhidao.baidu.com/question/1177745006240062179.html


联想到
我们为什么使用二进制去作为基本元素?

核心:两个状态的系统容易实现 、运算法则简单、可进行逻辑运算。

运算规则简单:节省设备。人们知道,具有两种稳定状态的元件(如晶体管的导通和截止,继电器的接通和断开,电脉冲电平的高低等)容易找到,而要找到具有10种稳定状态的元件来对应十进制的10个数就困难了

适合逻辑运算:逻辑代数是逻辑运算的理论依据,二进制只有两个数码,正好与逻辑代数中的“真”和“假”相吻合

容易实现:二进制在物理上最易实现存储,通过磁极的取向、表面的凹凸、光照的有无等来记录。

日常发车:


程序员的工作是相对孤独的,如何平衡呢?看下图:

图片等

你可能感兴趣的:(小威的算法厨房)