参考:
https://www.zhihu.com/question/20159860
https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
总结一些要点
为了使计算机运算数据更加简单,减法转换为加法: 1 - 1 => 1 + (-1)。为了支持这个功能,计算机对数据的存储需要一些额外的处理。
原码:最高位作为符号位,也就是对于1和-1的区别,只是最高位不一样。
反码:正数的反码和原码是一致的,而负数,除了最高位是1,其余位取反。
补码:正数的补码和原码是一致的,而负数的补码是负数的反码+1,+1之后可能会触发进位,导致最高位由1变成0,这种情况下所有位都是0了,也就是数字的值为0,因为0没有正负之分,所以可以认为补码表示法中,计算机认为最高位是1的都是负数,其余都是正数或者0
计算机采用补码的编码方式来存储数字,如以4位的数字长度表示 3 + (-3):
3的补码 = 3的原码 = 0011
-3的补码 = -3的反码(1100) + 1 = 1101
0011 + 1101 = 10000,因为这里数字位为4,超出的被丢弃掉,所以运算结果是0000 = 0
根据补码的规律,计算出实际的数值,如
1010 0000 0000 0000 0000 0000 0000 0000 -1之后
1001 1111 1111 1111 1111 1111 1111 1111 再除了最高外之外的位取反
1110 0000 0000 0000 0000 0000 0000 0000 ,除了符号位之后,其他位就是实际的正数数值了,复制到计算器中:
正数对应值为 1610612736 ,所以上面补码对应的值是 -1610612736
位运算
value >> n :数字补码右移n位,最高位保持不变,如4位长度的数字:1010(-6)右移1位成1101(-3),0111(7)右移1位成0011(3)
value << n:数字补码左移n位,最低位补0,左移过程中最高位会发生变化,数字的正负可能会颠倒,以上面的-1610612736 演示一下这个过程:
对应的补码是:1010 0000 0000 0000 0000 0000 0000 0000,左移动1位之后 0100 0000 0000 0000 0000 0000 0000 0000 对应的数值:
程序运行,结果一致:
所以左移不能简单理解为就是 乘以2 ,否则程序容易出bug。
value >>> n:与上面的右移,多了一个>,区别在于最高位不是保持不变了,而是固定补0,也就意味着,对于负数来说,右移补0之后,就变成正数了。