计算机:二进制表示和处理

位运算的技能点

  • 关键知识点:如果两个数相同,异或之后为0,3次之后就是数本身
  • 关键知识点2:任何数和1求与 &的话,都会只保留数字的最右边的那一位,其他的二进制位都为0
  • 向右移一位,是*2;向左是/2
  • 关键知识点:x右移k位是x/(2**k), X & 1是 X%2:可以用来判断是奇数还是偶数

计算机中的原码、反码和补码

如果是计算两个整数,计算机一定是先转换成补码,然后通过二进制的规则进行计算,如果得到结果符号位是0,直接就是原码,如果符号位是1,表示是负数的补码,所以通过-1,取反的操作得到原码,转换成十进制的整数。在计算机中,负数的二进制是用补码表示负数的。

这篇文章非常清楚的讲解了因为计算中只有加法器和需要为0进行唯一编码的关系,从而陆续在原码的基础上增加了反码、和补码

  • 反码: 为了标识负数
  • 补码:为了唯一标识0,所以8位表示数字的话整数是0-127,但负数就是-1 ~ -128,所以在计算机中0被认为是正数。

那在python中如何表示负数的补码:

bin(n & 0xffffffff)

上述代码对正数也同样适用。
如果是负数的原码,直接调用bin(n)
剑指offer中的第3道题最直接的方法:

# 前n个数字二进制形式中1的个数
# 这个程序最重要的逻辑是:i(必须是一个二进制) &(与操作)同样是二进制的(i-1)能够消掉一个二进制的1,最后不断的迭代之后变成了0
class Solution:
    def NumberOf1(self, n):
        if n < 0:
            n = n & 0xffffffff  # 计算负数的补码
        count = 0
        while n:
            n = n & (n - 1)
            count += 1
        return count

result = []
result2 = []
a = Solution()
m = 100
for i in range(m):
    result.append(a.NumberOf1(i))
    result2.append(bin(i & 0xffffffff)[2:].count('1')) # 通过直接调用python的函数库来是实现

print(result)  # 类函数调用方法
print(result == result2)

二进制位移

为什么需要位移操作?
参见位移的意义和方法
可以用在高低位的截取、哈希计算,和乘除计算中。简单来说,右位移是除以2(奇数近似除以2),左位移比较麻烦,因为符号位会参与移动,所以会出现正变成负,负变成正的情况。

在左移<<与右移>>两种运算中,符号位均参与移动,除负数往右移动,高位补1之外,其他情况均在空位处补0。
这句话其实是对下面分情况描述的总结:
左移:最左边的n位被丢弃,在最右边补上n个0
右移:最右边的n位被丢弃,如果是负数最左边补n个1;如果是正数补n个0 。

负数是不能在原码的基础上进行操作的,需要首先转化成补码才能进行移位运算,并且运算的结果并不是直接结果,还是需要将其转化为原码才能当做运算结果输出!
原文链接计算机用补码存储负数,负数的位移需要先转换成补码

这一篇把原码、反码、和补码都讲的比较清楚原码+ 补码和位移操作 ,但在做位移操作的时候有必要先转换为补码吗?另外最后一步从补码转换为原码的时候直接取反+1,这个和-1再取反的效果是一样的。

二进制计算相关

1. 整数的二进制计算 - 转换补码再计算

整数的二进制计算 - 转换补码再计算
计算机是将所有数变成补码,然后再进行二进制相加,然后将补码转化为原码,就得到可以转化成十进制的二进制。正数而言:原码、补码和反码都是一样的,需要做处理的是负数。
在这里插入图片描述

2. 单纯的二进制加法

python实现二进制加法,这里看起来和符号位没有什么关系,也就是上面从带符号整数变换到二进制,然后再计算是不一样的处理场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值