群里一个转码问题的灵魂拷问

背景

这几天确实太忙了,之前是日更,说上班后来个隔日更,还是坚持不了。完成Q1季度的考评后发现群里有人问了一个问题,非常的有意思。当时我也是非常的懵逼,然后想自己尝试的去解决一下。

问题是:0xee 0xb9short得到 -4423 为什么?对啊,为什么?我TM也想知道。

http://static.cyblogs.com/QQ20200411-001905@2x.jpg

其实到这里,我先总结一下:

  • 计算机为什么能计算你这么快,原因是它只会处理0与1,二级制;
  • 其实到硬件上面表现的就是电流信号、脉冲信号;
  • 计算机虽然支持减法,乘法,除法,实际上底层只会一种算法,那就是加法;

这也就是当时大学老师跟我们说的,别以为计算机很厉害,其实它很傻逼。每一步操作都需要设定好逻辑与程序。

恶补基础知识点

我们还是梳理一下基础知识吧~

  • 1、byte:有符号(意思是有正和负),在网络传输中都是会用到byte的,它占1个字节,共8位,比如说11111111就可以用1个byte表示,转化为10进制:- (2的6次+2的5次+2的4次+2的3次+2的2次+2的1次+2的0次) = -127。其中前7位表示数字,最高位表示符号,0为正,1为负。范围是 (-2的7次 ~ 2的7次 - 1),那为什么前面最小是-127,范围最小又是-128呢?因为规定-0(10000000)为-128。

  • 2、short:有符号,占2个字节,共16位。同byte一样,它的取值范围就是 (-2的15次 ~ 2的15次 - 1)。

  • 3、int :有符号,占4个字节,共32位。它的取值范围就是(-2的31次 ~ 2的31次)。

  • 4、long:有符号,占8个字节,共64位,它的取值范围就是(-2的63次 ~ 2的63次)。

  • 5、^:表示异或位运算,两者相同则为0,两者不同则为1。比如说15^2,15用二进制表示就是1111,2用2进制表示就是0010,两者进行异或运算,结果就是1101,转换为十进制就是13。

  • 6、|:表示或运算,两者只有有一个为1就为1, 比如说13|2,13用二进制表示就是1101,2用二进制表示就是0010,两者进行或运算,那么结果就是1111,转换为十进制就是15。

  • 7、&:表示与运算,两者都为1就为1,其余都为0,比如说15&2, 13用二进制表示就是1111,2用二进制表示就是0010, 两者进行与运算,那么结果就是0010,转换为十进制就是2。

  • 8、~:取反,就是本来是0变成1,本来是1变成0。

计算机中存储是用补码!!,同时注意一下计算省略了高位不变部分

我举个例子,比如说-15|3等于多少呢?有些人会觉得-15转化为二进制就是10001111,而3转化为二进制就是00000011,那么结果应该是10001111呀,转换为十进制就是-15呀?大家可以自己写个demo就会发现是不对的。要注意在计算机中所有的都是用补码的形式存储的,之所以上面介绍两个正数是对的,因为正数的反码和补码都是一样的。而负数求补码应该是出去符号位取反+1,我们再来看看这个题-15|3,其中-15的原码为10001111,反码为11110000,那么补码就是11110001,然后3的补码为00000011,两者进行或操作就是11110011,你以为结束了么?还没有,再又要求它的原码了,原码就是补码再求补码再+1(是不是已经晕掉了?),也就是10001101,结果就是-13。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
求 -15|3

[-15]原码 = 10001111
[-15]反码 = 11110000 //原码求反码符号位不变
[-15]补码 = 11110001 //反码+1等于补码

[3]原码 = 00000011
[3]反码 = 00000011 //正数都一致
[3]补码 = 00000011 //正数都一致

-15|3 = 11110011 //两个补码进行或操作

[结果]补码 = 11110011 //上面求得的值
[结果]反码 = 10001100 //符号位不变
[结果]原码 = 10001101 //反码+1

100001101 转化为十进制就是-13

开始解他那道题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@sophist 其实这个是基础知识,我们在计算机的存储里面short16位,最大数据存储量是65536,数据范围是-32768~32767之间。

0xee 0xb9 → -4423

16进制对应二进制:11101110 10111001

high << 8 | low & 255 低位保持不变

11101110 00000000

00000000 10111001
------------------
1110111010111001 第一位代表符号位,这个数字肯定是负数

取不骂 + 1
1001000101000110 + 1 = 1001000101000111 = -4423

这样子结果就得到了:-4423。

如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员简栈文化-小助手(lastpass4u),他会拉你们进群。

简栈文化服务订阅号