py3笔记34:位运算符

1、概述

计算机中数在内存中以二进制形式进行存储
位bit:计算机中处理数据的最小单位,其取值只能是0或1
字节Byte:计算机处理数据的基本单位,通常系统中一个字节为8位,即1Byte=8bit
=>位运算:直接对整数在内存中的二进制进行操作
=>执行效率高(在程序中尽量使用位运算进行操作)

序号 符号 描述 运算规则 实例
1 & 两位数都为1时,结果才为1 1&1=1,1&0=0,0&0=0
2 | 两位都是0时,结果才是0 1|1=1,1|0=1,0|0=0
3 ^ 异或 两个位相异为1,相同为0 11=0,10=1,0^0=0
4 ~ 取反 0变1,1变0 0=1,1=0
5 << 左移 各二进制全部左移若干位,高位丢弃,低位补0 11二进制=0b1011;左移:44,二进制:0b101100
6 >> 右移 各二进制全部右移若干位:正数左补0,负数左补1;右边移出的丢弃 >>1即/2

注意:计算机中位运算操作,均是以二进制补码形式进行

2、原码、反码、补码

原码:用最高位表示符号位,其余表示数值位的编码称为原码。(正数的符号位为0,负数的符号位是1)
反码:

  • 正数的反码:自身
  • 负数的反码:符号位保持不变,数值位逐位取反

补码:

  • 正数的补码:自身
  • 负数的补码:负数的反码+1
    注:补码再求一次补码的操作,可得到原码
1+(-1)=0
bin(1)=0000 0001
bin(0)=0000 0000
-1的二进制只有是:1111 1111 ;依次叠加进一,导致超出8位类似溢出,才能成立

==>负数num的二进制数(有符号数),则可视为无符号数的(2**n+num)的二进制数
a = -4
print(bin(2**8+a))  
# a=-1,0b11111111
# a=-4,0b11111100

3、应用

3.1 按位与&

应用1:与1按位与,可获取对应二进制数的最低位
应用2:与按位与,可使该数低位的一个字节清零

# 按位与&
a=1  # 补码 01
# b=-1 # 补码 11
b = 9 # 101
print(a&b) # 1
a=0  # 补码0
print(a&b) # 0

3.2 按位或|

def get_huo():
    # 按位或|
    a=9  # 补码 0000 1001
    b=20 # 补码 0001 0100
    print(a|b) #0001 0101
    print(bin(a|b))
    # 1+4+16
# 引申
def get_bin(num:int):
    # 求num的二进制数
    res_bin=""
    while num: # 辗转相除
        res_bin=str(num%2)+res_bin  # 
        num//=2  # // 整除
        print(res_bin,num)
    return res_bin
print(get_bin(10))  # 1010

3.3 按位异或^

不同为1,相同为0

# 按位异或
# 相同则为0,不同则为1
#       110 #  6
#       100 # 4
# 异或  010
a=6
b=4
# print(bin(6),bin(4))
print(a^b," ",bin(a^b))

特点:
1、a^0=a.即0与任意数按位异或都得该数本身
1^0=0;0^0=0
2、1与任意二进制位按位异或都得到该位取反(0变1,1变0)
1^1=0, 0^1=1
3、a^a=0.即任意数与自身按位异或都得0
4、ab=ba
5、(ab)c=a(bc)
6、abb=a(bb)=a^0=a

3.4 左移<<

高位丢弃(不包括1),低位补0。左移时舍弃的高位不包括1,则每左移一位,相当于该数乘以2。
<<= 移动后赋值

a=-10
# 1000 1010
# 反码(符号位不变,其他取反) 1111 0101
# +1 得补码 1111 0110
# 左移n位(n=2): 11 1101 1000
# -1: 11 1101 0111
# 取反(符号位不变,其他取反):10 0010 1000 即1000 1010 末尾加n个0
print(bin(a))
# print(a<<2) # -40 ;但是a本身不变仍是-10
a<<=2
print(a)  # -40
a<<=2
print(a) # -160

3.5 右移>>

将运算符各个二进制全部右移若干位,正数左补0,负数左补1,右边移出的位丢弃。
>>= 右移后赋值

a=10  # 0000 1010
b=-10 # 1111 0110
print(a>>2)
# 左移2位,高位补0:0000 0010
print(b>>2)  # -3
# 左移2位,高位补1,得补码 1111 1101;-1:1111 1100 ;反码(符号位不变,其他取反) 1000 0011

3.6 按位取反~

~0=1 、~1=0
应用:~a+1=-a 即对任意数按位取反后加1,得该数的相反数

a=10 # 0000 1010
# =>取反 1111 0101(负数的补码)
# =>-1:1111 0100 =>反码(符号位不变,其他取反):1000 1011(其为负数=-11)
b = -10 # 1111 0110 # 存储的补码=>取反:0000 1001(正数,=9)
print(~a) # -11
print(~b) # 9

4、二进制数的正负

  1. 看是否无符号数/有符号数

若是有符号数,开头第一位是符号位,1表示负数,0表示正数

  1. 看是如何存储在计算机中

本身是没有正负概念的;需要知道是原码还是补码,才能进而推断它的原始的值。如10101010 ,若是无符号,则值=170;若是有符号数,则值=-89???==>存储前是有符号数,则按有符号数处理,存储前是无符号数,则按无符号数处理

  1. 最后,看操作系统的位数

若是8位,1111 1111是-1;若是16位的FFFF 是-1;若是32位的FFFF FFFF 是-1


5、小数的二进制数

小数部分,将其乘以进制n,取出整数部分作为二进制表示第1位;依次类推,直到小数部分为0

特殊情况,小数部分出现循环,无法停止,则用有限的二进制位无法准确表示一个小数,这也是在编程语言中表示小数会出现误差的原因
引申:Py3浮点数取整

# print(bin(0.1)) # TypeError: 'float' object cannot be interpreted as an integer
def get_float_bin(f:float,n:int)->str:
    """
    求浮点数的二进制数
    :param f:
    :param n: 二进制小数的结果保留n位
    :return:
    """
    f_int=int(f) # 整数部分
    f_bin=bin(f_int)[2:]
    # 小数部分math.modf也是ok的
    f_float=f-f_int
    bin_a=""
    while f_float and n:
        f_float*=2  # 2进制
        bin_a+=str(int(f_float)) # 取整数
        f_float-=int(f_float)# 取小数位
        n-=1
    while n: # 不足则补0
        bin_a+="0"
    return f"{f_bin}.{bin_a}"

print(get_float_bin(10.6,12))  # 1010.100110011001

引申:二进制小数转为十进制小数

def get_float_shi(s:str,n:int)->float:
    """
    二进制小数转为十进制小数
    :param s: 二进制小数
    :param n: 十进制小数的精确度
    :return: 十进制小数,小数点后n位
    """
    i,f=s.split(".")
    i_shi = int(i,2)
    length=len(f)
    f_int=0
    flag=0.5
    for i in range(length):
        f_int+=int(f[i])*flag
        flag*=0.5
    # return round(i_shi+f_int,n)  # 10.6,保留了1位而不是10.60
    # return "%.2f"%(i_shi+f_int) # 10.60
    return eval("{:.2f}".format(i_shi+f_int))  # float()

a=get_float_shi("1010.100110011001",2)
# print(type(a))  # <class 'str'>=> <class 'float'>变为10.6
print(a)

参考:
1、位运算
2、负数的二进制表示方法
3、原码、反码、补码
4、小数的二进制表示法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容