目录
一、<< :左移运算符
二、>> :右移运算符
三、>>> :无符号右移
四、& :与运算
五、| :或运算
六、~ :非运算
七、^ :异或运算
拓展问题:
一:从计算速度上讲,移位运算要比算术运算快?
二:二进制的起源
日常发车:
参考文章:
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个数就困难了
适合逻辑运算:逻辑代数是逻辑运算的理论依据,二进制只有两个数码,正好与逻辑代数中的“真”和“假”相吻合
容易实现:二进制在物理上最易实现存储,通过磁极的取向、表面的凹凸、光照的有无等来记录。
程序员的工作是相对孤独的,如何平衡呢?看下图:
图片等