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

2020-04-02 11:33:41 +08:00
 SystemLight

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

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

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

1690 次点击
所在节点    程序员
7 条回复
marcong95
2020-04-02 11:57:14 +08:00
因为你的输出结果有个负号啊

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

难道你觉得是 “符号取反+数字取反” 分开操作再合成一个整数?
SystemLight
2020-04-02 13:37:28 +08:00
理解了,一开始我考虑错了,想的是对部分取反操作,也就是 二进制 11 取反后是 00, 符号取反,忽略了整型实际内存占用大小。
justou
2020-04-02 14:19:21 +08:00
曾经遇到过类似问题 https://www.v2ex.com/t/369580
SystemLight
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))

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/658588

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX