numpy(四)位运算介绍、位运算符的运用

1.介绍

        大家都知道计算机的世界是二进制世界,而位运算就是直接对二进制进行操作,这就减少了时间的开销,更为致命的是python的速度慢于c语言10-20倍之间,故掌握位运算还是很有必要的。

2.十进制与二进制的转换

        这儿简单的说一下十进制对二进制的转换。

        (1)十进制转为二进制,使用的辗转相除法,获得的余数的从下至上就是二进制数。见下例

        (2)二进制转十进制,就是简单的指数相加。见下例

        

3.位运算符

        位运算符一共有6个,分别为按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、按位左移(<<)、按位右移(>>),这儿给个表格,总结一下运算符的名称、算符和应用,想看详细的见下面

位运算符名称算法应用
按位与(&)0&0=0、0&1=0、1&0=0、1&1=1判断奇偶性
按位或(|)0|0=0、  0|1=1、  1|0=1、 1|1=1
按位异或(^)0^0=0、0^1=1、   1^0=1、1^1=0交换两数(无中间变量)
按位取反(~)~0=1、  ~1=0
按位左移(<<)a<<n:将a的二进制左移n位,最左边n位丢弃,右边补0一个数乘2的n方
按位右移(>>)a>>n:将a的二进制右移n位,最右边n位丢弃,左边补0

(1)按位与(&)

        按位与对二进制怎么操作的,就是

            0 & 0 = 0 

            1 & 0 = 0

            0  & 1 = 0 

            1 & 1 = 1

        换句话说,这种操作有点像逻辑上的且关系(即True and False)     

        举个例子 

a = 18
b = 15
print('a的二进制是{},b的二进制是{}'.format(bin(a), bin(b)))
print(a&b)

"""
结果:
a的二进制是0b10010,b的二进制是0b1111
2

"""

 使用表格来说明具体的操作

ab按位与(&)
10(没有补0)0
010
010
111
010

这样获得二进制数为10 ,那么10进制数就为2^(1)+2^(0)=2

(2)按位或(|)

        按位或(|)与按位与(&)类似,操作为 

         0 | 0 = 0

         0 | 1 = 1

         1 | 0 = 1

         1 | 1 = 1

        其余算法与按位与(&)一模一样

(3)按位异或(^)

 简单的说,就是两个位相同为0,相反为1,操作为:

       0 ^ 0 = 0, 
  1 ^ 0 = 1, 
  0 ^ 1 = 1, 
  1 ^ 1 = 0

(4)按位取反(~)

     简单的说,就是0 变 1,1 变 0

         ~0 = 1

         ~1 = 0

(5)按位左移(<<) 

      简单的说," a<< n ":将a的二进制位全部向左移n位,最左边n位舍弃,右边补0

    (注意二进制数前面有0作为填充,0的个数与变量的类型有关系)

举个例子

a=18
n=3
print(a<<3)

"""
结果为:144
前面已经得到 a 的二进制为 10010
左移3位,即 10010000   转为10进制: 2^7+2^4=128+16=144

"""

(6)按位右移(>>)

      简单的说,"a>>n":将一个数的二进制位全部向右移n位,最右边n位舍弃,左边补0,与按位左移(<<)反过来。

4.位运算符的运用

  4.1按位与(&)

    4.1.1  判断奇偶性

        当一个数a,与1进行按位与操作,即

        (1) a & 1 = 0,则a为偶数

        (2) a & 1 = 1,则a为奇数

        为什么会有这个性质呢?

        证明如下:我们来看a的二进制为 0000 0001,根据按位与的性质0&1=0、0&0=0,可知结果中的二进制只有最后一位不能确定,其余均为0。又知计算a的二进制时,由于辗转相除是反过来的,故a的二进制的最后一位即为a/2的余数,不妨设其为b。

         可知当b为0时,这时b&1=0,故为偶数(因b为a对2的余数)

                当b为1时,这时b&1=1,为奇数(因b为a对2的余数)

   4.2按位异或(^)

       4.2.1交换两个数(不用中间变量)

        当有2个数 a 和 b,执行下面代码段即可实现交换2个变量。

a=18
b=15
a = a ^ b
b = b ^ a
a = a ^ b
print('a={},b={}'.format(a,b))


"""
结果
a=15,b=18
"""

        那为什么会有这种性质呢?

        证明写在代码段中,见下

证明如下:假设a与b均为二进制数
对二进制b与a^b的情况作讨论(讨论的是二进制中的1个数)
(1)当b二进制中的某个数为0时,若a^b 相对应得这个数也为0,由异或(^)性质,
   可以得到初始时a为0,这时做 a = a ^ b = 0 (假设条件)
   再做 b = b ^ a(ps:0 ^ 0 = 0) 对应的这个数字为0,即b = a (ps:初始的a)
   再做 a = a ^ b(ps:0 ^ 0 = 0) 对应的这个数字为0,即a = b (ps:初始的b)
(2)当b二进制中的某个数为0时,若a^b 相对应得这个数为1,由异或(^)性质,
   可以得到初始时a为1,这时做 a = a ^ b = 1 (假设条件)
   再做 b = b ^ a(ps:0 ^ 1 = 1) 对应的这个数字为1,即b = a (ps:初始的a)
   再做 a = a ^ b(ps:1 ^ 1 = 0) 对应的这个数字为0,即a = b (ps:初始的b)
(3)当b二进制中的某个数为1时,若a^b 相对应得这个数为0,由异或(^)性质,
   可以得到初始时a为1,这时做 a = a ^ b = 0 (假设条件)
   再做 b = b ^ a(ps:1 ^ 0 = 1) 对应的这个数字为1,即b = a (ps:初始的a)
   再做 a = a ^ b(ps:0 ^ 1 = 1) 对应的这个数字为1,即a = b (ps:初始的b)
(4)当b二进制中的某个数为1时,若a^b 相对应得这个数为1,由异或(^)性质,
   可以得到初始时a为0,这时做 a = a ^ b = 1 (假设条件)
   再做 b = b ^ a(ps:1 ^ 1 = 0) 对应的这个数字为0,即b = a (ps:初始的a)
   再做 a = a ^ b(ps:1 ^ 0 = 1) 对应的这个数字为1,即a = b (ps:初始的b)
综上:无论b二进制唯0或1,做次操作均可交换a和b,推至n个二进制数,不失一般性,仍然成立

  4.3 按位左移(<<)

     4.3.1 一个数乘2的n次方更快

        有一个数a,左移n位,且左移时被溢出舍弃的高位中不包含1

        进行a<<n,即进行 a*2^n 的操作,当然如果a=1,就是2^n操作了。

        那么为什么会有这种性质呢

        证明如下:先进行一般性假设

        

         可以得到此时

         a=2^{k+n+m+j-1}+...+2^{k+n+m+1-1}+2^{k+n-1}+...2^{k+1-1}

        当a向左移动n位时,

        

        可以得到新的a=2^{k+n+n+m+j-1}+...+2^{k+n+n+m+1-1}+2^{k+n+n-1}+...+2^{k+n+1-1}

         即a=a*2^{n}

        推广至一般情况,仍然成立。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山上有多花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值