位运算
今天我要来讲一下运算符。用PHP来做示范!
提到位运算符肯定要谈到二进制。我会尽可能讲的让所有人看懂!
先看下用法:
源自于:PHP参考手册
再讲解之前,我们要熟记这6句话,记住他们,位运算就会变得很简单
1.二进制的最高位是符号位,0表示正数,1表示负数!一定要记住了,不能忘记!
2.正数的原码、反码、补码都一样!-->马上我来讲解什么是原码!
3.负数的反码=它的原码符号位不变,其他位取反。什么取反举个例子比如这样{0-->1 || 1-->0}
4.负数的补码=它的反码+1
5.0的反码、补码都是0
6.在计算机运算的时候,都是以补码的方式来运算的
-------------------------------------------------------------------------------------------------------------------
那么什么是原码呢?
原码:用二进制表示一个数字就叫做原码!
-->然后我们开始我们的位运算之路!||
从最简单的开始讲解:
按位与(&)
先学习按位与,在逻辑数学上面我们学过与,我们知道与是and这里差不多但是是用字符来表示!
含义大家应该都清楚,就是两个都为真才为真!
通过下面一张图片让大家真正理解什么时候是False:
一图胜千言!
现在我们来学习按位与(&)
来看点实际操作吧:
这里输出的是2;看到这里,我们不禁有一丝疑惑?
说了当两者都为1(真)才算1;但是我们这里是2和3为什么我们这里会选择2呢?
很奇怪是不是?
让我们来揭开他的庐山真面目!
因为一个整数一般四个字节,这里我把他拆分成四段!
2&3,这个小玩意他是如何运算的呢?
//看了上面那6句话,现在派上了用场! 二进制的2等于多少?二进制的2就是2的原码是多少! 2的原码:00000000 00000000 00000000 00000010 3的原码:00000000 00000000 00000000 00000011 //谨记前面我提到的六句话:当为正数的时候,原码,反码,补码都一样! //之前我谈到了第六句话:计算机运算的时候是以补码 的方式来运算的 //那么现在应该是: 2的补码:00000000 00000000 00000000 00000010 3的补码:00000000 00000000 00000000 00000011 //此时此刻2&3应该是多少?我们看了按位与的概念了现在我们开始吧! 2&3 00000000 00000000 00000000 00000010 //当2和3中都为1的时候才为1,一个为1一个不为1那么 就不行!
再来说下按位或(|)
概念很清楚,按位或就相当于逻辑数学当中的or,两者比较有任何一个为真(1)就为真!
答案是3,咱们来推导它!
//看了上面那6句话,现在派上了用场! 二进制的2等于多少?二进制的2就是2的原码是多少! 2的原码:00000000 00000000 00000000 00000010 3的原码:00000000 00000000 00000000 00000011 //谨记前面我提到的六句话:当为正数的时候,原码,反码,补码都一样! //之前我谈到了第六句话:计算机运算的时候是以补码 的方式来运算的 //那么现在应该是: 2的补码:00000000 00000000 00000000 00000010 3的补码:00000000 00000000 00000000 00000011 //此时此刻2&3应该是多少?我们看了按位与的概念了现在我们开始吧! 2|3 00000000 00000000 00000000 00000011 //因为是按位或所以有任何一个为1就为1
再来学习按位异或就是Xor
这是概念,这个有点恶心,大家不要搞乱!一个为1,另一个为0的时候才为1!
输出的是1,让我们来推导它!
//看了上面那6句话,现在派上了用场! 二进制的2等于多少?二进制的2就是2的原码是多少! 2的原码:00000000 00000000 00000000 00000010 3的原码:00000000 00000000 00000000 00000011 //谨记前面我提到的六句话:当为正数的时候,原码,反码,补码都一样! //之前我谈到了第六句话:计算机运算的时候是以补码 的方式来运算的 //那么现在应该是: 2的补码:00000000 00000000 00000000 00000010 3的补码:00000000 00000000 00000000 00000011 //此时此刻2&3应该是多少?我们看了按位与的概念了现在我们开始吧! 2^3 00000000 00000000 00000000 00000001 //因为是按位异或是其中一个是1,另一个是0的时候,结果才设为1,否则就是0
这三个基础就这样讲完了!大家多加练习就行!
现在重头戏!按位取反(~)
我记得我们学逻辑数学的时候老师讲过(头上一个-)代表非,比如1是真,非1就是0;在编程里面意思是一样的,用法不同罢了!
现在我们还得知道很重要的知识点!
1.不管是一个正数还是负数,都要被转换成补码,然后进行运算!然后输出显示的时候,是原码!
我们来看看概念吧!
这里我们减少压力,其实写到这里我也有点乱了!加油!
我刚学这个的时候,我很震惊,我很困惑为什么是这个答案!!!!不应该是5吗?非-5不就是5吗?哎,还是太年轻了!
我们来推导吧!
这个还不算复杂:
~-5: //这里-5不是正数所以我们很悲催需要从头算起 //谨记我前面的六句话,套用公式 -5的原码:10000000 00000000 00000000 00000101 -5的反码:11111111 11111111 11111111 11111010 -5的补码:11111111 11111111 11111111 11111011 //这里有个很重要的点:从原码-->反码-->补码 /*负数的补码=它的反码+1 关键:反码-->补码这个过程其实变化的只是最后一个数字!!它的反码+1加的是最后一个数字,只有最后一个数字需要变化*/ 这里我们得到补码然后我们~-5就是正数 ~-5补码:00000000 00000000 00000000 00000100(补码)=4 //因为~-5相当于非-5就是5为真,是正数,因为正数原码,补码,反码都一样所以这里补码=原码,输出原码! //就是这样 ~-5原码:00000000 000000000 00000000 00000100=4
我们再来推导一个吧,先看代码:
这个推理就有点复杂了,其实记住我前面的那6句话,这个最多只能算麻烦!
推导吧!看它的过程,怎么诞生的-3:
2的原码:00000000 00000000 00000000 00000010 2是正数2的反码就是: 2的反码:00000000 000000000 000000000 00000010 ~2补码: 11111111 11111111 11111111 11111101 (补码)-->原码 //从补码-->反码 //反码=补码-1,减一变化的是最后一个数字!! ~2反码: 11111111 11111111 11111111 11111100 //原码=反码的取反,符号位不变化! ~2原码: 10000000 00000000 00000000 00000011=-3 //这样得到-3
按位取反(~)就这样讲完了!
下面讲解的东西非常重要,其实我讲的这些都很重要。(*^__^*) 嘻嘻……
位移运算符讲解
先看概念,先讲右移运算符:
这是概念!其实这个真的有点复杂,比上面的那个复杂点!
这个概念有点坑咱们先不要管!
记住我的一句话走遍天下都不怕:算术右移:低位溢出,符号位不变,并用符号位补溢出的高位。
先讲简单的吧,看代码:
然后是推导,内部的推导一遍:
1>>2: //2是右移了几个! 1是正数,因为正数的原码、反码、补码都一样! 就是右移: 1的原码00000000 00000000 00000000 00000001 因为右移了两个:00000000 00000000 00000000 00000000 //这里为啥是0呢?让我们看看它的诞生和发展! 1.00000000 00000000 00000000 00000001 2.0??00000000 00000000 00000000 000000//发现最后两个的00被去掉了 3.去掉的两个位置用符号位就是第一个数字0来补齐! 4.得到00000000 00000000 00000000 00000000=0 5.故得0
这个我演示完毕了,我现在用负数来做演示!
看代码吧:
这里输出的是-1;我们现在来推导它:
-1>>2:<--->2代表右移两位,3就代表右移三位,同理! //-1不是正数,所以我们需要重头搞起! -1原码:100000000 00000000 00000000 00000001 -1反码:111111111 11111111 11111111 11111110 //补码=反码+1 ,反码里面1+1=1; -1补码:111111111 11111111 111111111 11111111 //因为在计算机里面用补码来运算然后再用原码来输出所以我们右移两位 -1>>2:111111111 11111111 11111111 11111111 //右移两位的诞生和结果过程推导: 1.11111111 111111111 11111111 11111111 2.1??1111111 11111111 11111111 111111//这里去掉了最后两位数字,因为右移了两位数字,去掉的两位用符号位补全! 3.补码:11111111 11111111 11111111 11111111 补码--->原码: 公式=补码-1=反码 反码:111111111 111111111 111111111 111111110//-1只要修改最后一个数字即可 //从反码转换成补码,不要改变符号位就是第一个数字,其余数字都取反 //然后得到原码: 原码:100000000 000000000 000000000 000000001=-1 //我前面提过在二进制中1代表负数! 00000000 00000000 00000000 00000001=1 10000000 00000000 00000000 00000001=-1
终于算是讲完了右移运算符,呼~~最后一个知识点,左移运算符,我感觉这个部分是所有知识点里面最容易理解的!
先看概念:
再看代码:
这里大家仔细看概念,多读几遍概念!
我们推导它:
2<<3:2左移了三位 那么就是2*8=16 答案是16; 为什么是16呢? //概念上面讲的非常清楚! 每一次移动都表示"乘以 2",只要移动一次就乘以2; 这里我左移了三次 第一次的时候 第二次的时候 第三次的时候 x2=2; x2=4; x2=8 乘以是在之前的基础上再乘以2 所以现在答案是:2*8=16; 再举个例子: 1<<2:这里输出的结果就是4; 左移两次就是: 第一次 第二次 x2=2; x2=4; 所以1*4=4;
不信咱们看结果!
讲解完毕,真的很累,但是真的学到了很多!这个适用于所有编程,修改语法即可!
路虽远,行则必达。事虽难,做则必成!
转自https://www.cnblogs.com/piaomiaohongchen/p/6680580.html