a = 2 # 0b10 print(bin(~a)) # -0b11
b = -2 # -0b10 print(bin(~b)) # 0b01
负数时候连同符号位按位取反没有问题,但是正数的取反操作算出来的数值为什么不像是取反操作呢,这是什么原理,有没有大佬说明下 !
1
marcong95 2020-04-02 11:57:14 +08:00
因为你的输出结果有个负号啊
2 == 0b10 == 0 ...10 -3 == -0b11 == 1 ...01 |
2
lostpg 2020-04-02 12:01:55 +08:00 via Android
整数用补码表示,2 和-3 的补码正好相反。
|
3
AddictX 2020-04-02 12:14:49 +08:00
我反正是简单理解成 ~x = -(x+1)
具体导致这样运算的原因可以看看 https://segmentfault.com/q/1010000005697515 |
4
imn1 2020-04-02 12:56:25 +08:00
你拿个计算器 app 按一下就知道了
-3 的二进制是 1111111111111111111111111111111111111111111111111111111111111101 python 没有内置 unsigned int,都是换成 signed int 显示 难道你觉得是 “符号取反+数字取反” 分开操作再合成一个整数? |
5
SystemLight OP 理解了,一开始我考虑错了,想的是对部分取反操作,也就是 二进制 11 取反后是 00, 符号取反,忽略了整型实际内存占用大小。
|
6
justou 2020-04-02 14:19:21 +08:00
曾经遇到过类似问题 https://www.v2ex.com/t/369580
|
7
SystemLight OP # 回复自己的一点理解
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)) |