(〜)为什么我的位没有翻转?

时间:2014-11-28 06:13:09

标签: python bitwise-operators

我认为〜应该将1s变为0,反之亦然。我在我的代码中使用它,但我得到-2s和-1s。

def inverse_graph(graph):
    # for each vertex in graph
    revg = list(graph)
    for i, line in enumerate(revg):
        for j, vertex in enumerate(line):
            if  i != j:
                # flip value
                graph[i][j] = ~ graph[i][j]
                #if vertex == 0:
                #    graph[i][j] = 1;
                #else:
                #    graph[i][j] = 0;
    return revg



def test():
        g1 = [[0, 1, 1, 0],
              [1, 0, 0, 1],
              [1, 0, 0, 1],
              [0, 1, 1, 0]]
        assert inverse_graph(g1) == [[0, 0, 0, 1],
                                     [0, 0, 1, 0],
                                     [0, 1, 0, 0],
                                     [1, 0, 0, 0]]
        g2 = [[0, 1, 1, 1],
              [1, 0, 1, 1],
              [1, 1, 0, 1],
              [1, 1, 1, 0]]
        assert inverse_graph(g2) == [[0, 0, 0, 0],
                                     [0, 0, 0, 0],
                                     [0, 0, 0, 0],
                                     [0, 0, 0, 0]]

............................................... .................................................. .................................................. .................................................. ........

4 个答案:

答案 0 :(得分:4)

实际上,-2 ~1。 Two's complement,还记得吗?

>>> bin(1)
'0b1'
>>> bin(~1)
'-0b10'

问题是:你不是使用比特,而是使用整数。所以你想要恢复使用例如布尔(读得不太好)或者你想使用像0 if x else 1这样的表达来翻转你的元素。

提示:您可以使用理解来更优雅地写出来:

>>> flipped = lambda graph: [ [0 if x else 1  for x in row]  for row in graph]
>>> flipped( [ [1, 0], [0, 1] ] )
[[0, 1], [1, 0]]

答案 1 :(得分:2)

使用numpy会更容易。

>>> import numpy as np
>>> g1=np.array([[0, 1, 1, 0],
...              [1, 0, 0, 1],
...              [1, 0, 0, 1],
...              [0, 1, 1, 0]])
>>> g2=1-g1
>>> g2
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [0, 1, 1, 0],
       [1, 0, 0, 1]])

〜将使用布尔数据类型:

>>> g1=np.array([[0, 1, 1, 0],   # 1 represents True and 0 represents False
...              [1, 0, 0, 1],
...              [1, 0, 0, 1],
...              [0, 1, 1, 0]], dtype=bool)
>>> ~g1
array([[ True, False, False,  True],
       [False,  True,  True, False],
       [False,  True,  True, False],
       [ True, False, False,  True]], dtype=bool)

如果你希望{0}和1中的complement(~)而不是真假,那么这就可以了:

>>> ~g1+0
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [0, 1, 1, 0],
       [1, 0, 0, 1]])

答案 2 :(得分:2)

正如xtofl所指出的,Python的整数使用了两个补码表示。这意味着0的按位反转不是1,而是无限长的二进制1序列,它被解释为-11的倒数不是0,而是无穷多的,后跟一个零(即-2)。

当然,为每个整数存储的位数不是无限的。 Python通常会使用系统定义的C整数类型long(通常为32位或64位长),但溢出的操作将自动切换到Python自己的任意精度{{1如果值太大而无法拟合(在Python 3中long类型内透明地处理此转换)。

无论如何,另一种解决方案是使用:

int

或者,如果您不介意这些值成为graph[i][j] = 1 - graph[i][j] 子类型int的实例:

bool

Python的graph[i][j] = not graph[i][j] 值仍可用作数字(bool的工作方式与False类似,0就像True一样。唯一真正的区别是他们会用文字而不是数字打印出来。

答案 3 :(得分:0)

虽然其他人都是对的,但更简单的说0 if x else 1的方法是not xint(not x)

not x如果False则返回x != 0,否则返回TrueFalseTruebool s,是int的子类。它们可以很容易地用于计算,但是对于您希望获得正确01的情况,或者如果您需要它们来索引dict,{{1}可能会更好。