概述
最近在学习C语言,碰到了这些概念,花费了一下午的时间,总结出了一些结论,仅供参考。
先说一些规定,也就是定义。
- 位
加法
有四种情况: 0+0=0
0+1=1
1+0=1
1+1=10(向高位进1,就是10进制,满10进1 一样的运算)
0 进位为1
减法
0-0=0
1-0=1
1-1=0
0-1=1(向高位借位) 借1当10 借1当2 算就行了
参考
链接: https://jingyan.baidu.com/article/851fbc379ef4173e1e15ab71.html
乘法:0 * 0 = 0,0 * 1 = 0,1 * 0 = 0,1 * 1 = 1;
除法:0÷0 = 0,0÷1 = 0,1÷0 = 0 (无意义),1÷1 = 1;
-
概念
计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同 [1] 。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理 -
原码
是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
简单直观;例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011 符号位,就是第一位,高位,如果是32位的系统,那么就是10000…0001011 一共32个,符号位就是第一位。
以8位机器数为例,整数的“+0”原码为0,0000000;整数的“-0”原码为1,0000000
原码不能直接参加运算,可能会出错。例如数学上,1+(-1)=0,而在二进制中
原码
原码
00000001+10000001=10000010,换算成十进制为-2。那么问题来了10000010凭什么就是-2了呢??? 1代表符号位,0x2的0次方+1x2的1次方 = 2 = -2;但这种计算是错误的,因为10000010是原码,不是补码,计算机存储的都是补码,所以这也就是不能使用原码存储的原因,不方便计算的!
那么补码就来了,我们来看看补码是怎么计算的。
正数的补码是本身。
负数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1 。
0的补码,8个0。
例子
+5的补码是00000101
+9的补码是00001001
-5对应正数5(00000101)因为是负数所以(10000101→所有位除符号位(1)取反也就是将0000101取反再和符号位拼接得(11111010)→加1(11111011) 最后一位0+1=1
0,也就是11111011 这就是-5的补码,计算机中也是这样存储的。
5+(-5) = 00000101 + 11111011 = 00000;
24个0拼接00000101 + 24个1拼接11111011 = 逢2进1 ,1+1=10。得到n个0的结果。
-
反码和位运算
多用于原码和补码的中间运算,为什么要要有这种操作,我只能说规定。
位运算,常见的都有哪些呢??位运算有什么用呢?在某些算法中,如果用位运算有出其不意的结果。
=== 1. and运算 & ===
相同位的两个数字都为1,则为1;若有一个不为1,则为0。
00101
11100
00100
=== 2. or运算 | ===
相同位只要一个为1即为1。
00101
11100
11101
=== 3. xor运算 ^ ===
相同位不同则为1,相同则为0。
00101
11100
11001
=== 4. not运算 ~ ===
0变1,1变0 这里要注意,取反,和反码是两个概念啊!! -
二进制和十进制的转换
网上一堆帖子,结合上面说的php函数,我们只能自己背下里这些转换的原理
十进制转二进制
数值为正数时
用该正数,递归除2,直到商等于0停止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
最后的商是0的,不要算进去,不够的在高位补充0.
789=1100010101(B)
789/2=394 余1 第10位
394/2=197 余0 第9位
197/2=98 余1 第8位
98/2=49 余0 第7位
49/2=24 余1 第6位
24/2=12 余0 第5位
12/2=6 余0 第4位
6/2=3 余0 第3位
3/2=1 余1 第2位
1/2=0 余1 第1位
商0 结束 商不是第一位
32/64位补零+1100010101 这里得到的原码,其实在计算机中是补码存储的,正数的补码就是原码。
数值是负数
以十进制-55为例
取得该数值的绝对值为55,原码为0011 0111,这就是-55的原码 = -0011 0111 = 1011 0111
先将原码转为反码,上面有说过,不细讲了,直接放数据。
0011 0111 -> 1011 0111->1100 1000->1100 1001 补码
二进制转十进制
二进制数首位字符为符号位,0表示正,1表示负
二进制数值首位为0
例子中通常是8位二进制10000100,如果是32位系统。10000…00100。不要问我为什么要说这句话,我觉得很关键。
二进制数值位数从后往前,依次计算第n位上数字乘以2的n-1次幂,所得到的和即为十进制数字;
以 0011 0111 为例:
1x2^0 + 12^1 + 1x2^2 + 02^3 + 1x2^4 + 1*2^5 = 1 + 2 + 4 + 16 + 32 = 55
则最终的结果是55
二进制数值首位为1
二进制首位为1则表示次二进制数值为负数,根据十进制转二进制的规则逆推即可;
以 1100 1001 为例:如果是32位的,那么就是1000…000001001001,这个值都是补码的。
① 1100 1001 减1 得到 1100 1000
② 取1100 1000 反码得到 1011 0111
③ 将1011 0111 转化成十进制为-55
则最终得到结果为 -55,也就是将负数的补码,转为负数的原码,再通过原码计算出值。
- php的函数
例子中针对-5的这种在计算机中以补码的形式存储,那么我就是被迷惑了,之前我们通用的那种十进制二进制转换,2的n次方啊,什么的,你觉得可能有负数吗???所以下面继续探讨。
这是网上大多数的例子,但是这个地方我有自己的个人理解。
php的两个函数。decbin 将十进制转换位二进制。
decbin(-5) 我是64位的系统1111111111111111111111111111111111111111111111111111111111111011这是结果。这个借结果就是补码的结果,说明这个函数还是很好使的。
这里举一个8位的例子
5的原码101,那就是0000 0101-》1000 0101-》1111 1010-》1111 10111 这个计算流程上面有写,所以证明没问题的。
再说另外一个函数。
bindec 将二进制转为十进制。
bindec() 将所有的 binary_string 值解释为无符号整数。这是由于 bindec() 函数将其最高有效位视为数量级而非符号位。
所以这函数,懂了吧,像用 decbin(-5) 得到结果,是无法当做bindec的入参的,至此我没有发现更好的办法,但是我们只要理解 整篇文章就可以了。
最后
以上就是魁梧悟空为你收集整理的PHP--位,位运算原码,补码,反码,二进制,十进制转换的全部内容,希望文章能够帮你解决PHP--位,位运算原码,补码,反码,二进制,十进制转换所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复