V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
SystemLight
V2EX  ›  程序员

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

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

    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
    曾经遇到过类似问题 https://www.v2ex.com/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   ·   实用小工具   ·   2658 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:08 · PVG 23:08 · LAX 07:08 · JFK 10:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.