Python 中取反操作符是如何算出来的,为什么正数的这么怪异,负数的正常? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
SystemLight
V2EX    程序员

Python 中取反操作符是如何算出来的,为什么正数的这么怪异,负数的正常?

  •  
  •   SystemLight
    SystemLight 2020-04-02 11:33:41 +08:00 2341 次点击
    这是一个创建于 2084 天前的主题,其中的信息可能已经有所发展或是发生改变。

    a = 2 # 0b10 print(bin(~a)) # -0b11

    b = -2 # -0b10 print(bin(~b)) # 0b01

    负数时候连同符号位按位取反没有问题,但是正数的取反操作算出来的数值为什么不像是取反操作呢,这是什么原理,有没有大佬说明下 !

    7 条回复    2020-04-30 14:30:28 +08:00
    marcong95
        1
    marcong95  
       2020-04-02 11:57:14 +08:00
    因为你的输出结果有个负号啊

    2 == 0b10 == 0 ...10
    -3 == -0b11 == 1 ...01
    lostpg
        2
    lostpg  
       2020-04-02 12:01:55 +08:00 via Android
    整数用补码表示,2 和-3 的补码正好相反。
    AddictX
        3
    AddictX  
       2020-04-02 12:14:49 +08:00
    我反正是简单理解成 ~x = -(x+1)
    具体导致这样运算的原因可以看看 https://segmentfault.com/q/1010000005697515
    imn1
        4
    imn1  
       2020-04-02 12:56:25 +08:00
    你拿个计算器 app 按一下就知道了
    -3 的二进制是 1111111111111111111111111111111111111111111111111111111111111101
    python 没有内置 unsigned int,都是换成 signed int 显示

    难道你觉得是 “符号取反+数字取反” 分开操作再合成一个整数?
    SystemLight
        5
    SystemLight  
    OP
       2020-04-02 13:37:28 +08:00
    理解了,一开始我考虑错了,想的是对部分取反操作,也就是 二进制 11 取反后是 00, 符号取反,忽略了整型实际内存占用大小。
    justou
        6
    justou  
       2020-04-02 14:19:21 +08:00
    曾经遇到过类似问题 t/369580
    SystemLight
        7
    SystemLight  
    OP
       2020-04-30 14:30:28 +08:00
    # 回复自己的一点理解

    c = 0b01
    b = -0b11

    # python 获取整型占用大小,可以使用 sys.getsizeof(num)
    # 原码是人看到的,补码是计算机看到的
    # c 的补码 0...001 ...代表省略的符号位,根据 int 大小值来的,我假设是 8 位的 int 大小,写全就是 00000001 这是补码,正数补码就是这个数的原码
    # b 的补码 1...101 ...代表省略的符号位,根据 int 大小值来的,我假设是 8 位的 int 大小,写全就是 11111101 这是补码,
    # 负数补码变原码,除了符号位其它位需要先按位取反再加一,就是这个数的原码。(先取反)10000010 (再加 1)10000011
    # c 的原码 00000001
    # b 的原码 10000011(最高位是符号位 0 是正数,1 是负数)

    # c 异或 b 实际上是补码在做运算,用我们假设的 8 位内存大小的整型演示
    # c: 00000001
    # b: 11111101
    # 结果:11111100 结果的补码就得到了,但是我们人看的时候计算机会转成源码,转原码先取反,符号位不动 10000011,再加一,10000100
    # 得到负的一个 0000100 数字,前面 0 省略掉,就是-0b100,用 python 运行看一下结果是不是这样

    print(bin(c ^ b))
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     902 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 22:17 PVG 06:17 LAX 14:17 JFK 17:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86