布尔运算符与位运算符的区别

106

我不确定何时应该使用布尔运算符和位运算符。

  • and& 的区别
  • or| 的区别

请问有人能告诉我在什么情况下使用每种运算符,以及选择其中一种会如何影响我的结果?


15
请注意,您将收到的答案大致适用于所有其他(主流命令式)语言。 - user395760
9个回答

107

以下是一些指导原则:

  • 布尔运算符通常用于布尔值,但位运算符通常用于整数值。
  • 布尔运算符是短路的,而位运算符不是短路的。

短路行为在这样的表达式中很有用:

if x is not None and x.foo == 42:
    # ...

如果使用按位 & 运算符,则此方法将无法正确运行,因为两侧将始终被计算,从而导致 AttributeError: 'NoneType' object has no attribute 'foo'。当您使用布尔运算符 and 时,如果第一个表达式为 False,则不会计算第二个表达式。同样地,如果第一个参数为 True,则 or 不会计算第二个参数。


16
补充:在Python中,&|^也是集合操作符。 - kennytm
7
在Python中,按位运算不允许混合类型,但布尔运算可以。例如, True or "True" 是可以的(它将返回第一个真值),但 True | "True" 将会抛出异常。 - Hannele
11
@Hannele 这与混合类型无关。按位操作只适用于整数,其他任何类型都会抛出异常。这里的重点是Python将False和True分别视为0和1:0 == False1 == True都为真。 - Nuno André
1
@NunoAndré 确实,那是一个更准确的解释。谢谢! - Hannele

30

以下是另一个差异,曾让我感到困惑:因为&(和其他位运算符)的优先级高于and(和其他布尔运算符),所以以下表达式会计算出不同的值:

0 < 1 & 0 < 2

对比

0 < 1 and 0 < 2

换句话说,第一个产生False,因为它等同于 0 < (1 & 0) < 2, 因此 0 < 0 < 2,因此0 < 0 并且 0 < 2


28
理论上,andor直接来自布尔逻辑(因此操作两个布尔值以生成一个布尔值),而&|将布尔与/或应用于整数的各个位。这里有很多关于后者如何工作的问题。
以下是可能影响您结果的实际差异:
  1. andor短路,例如True or sys.exit(1)不会退出,因为对于第一个操作数的某个值(True or ...False and ...),第二个操作数不会改变结果,因此不需要被评估。但是|&不会短路-True | sys.exit(1)会将您从REPL中抛出。
  2. &|是常规运算符,可以重载,而andor则被强制加入语言中(尽管用于布尔强制转换的特殊方法可能具有副作用)。
    • 这也适用于其他一些支持运算符重载的语言
  3. andor返回操作数的值,而不是TrueFalse。这不会改变条件中布尔表达式的含义-1 or True1,但是1也是true。但曾经用于模拟条件运算符(C语法中的cond? true_val: false_val,Python中的true_val if cond else false_val)。对于&|,结果类型取决于操作数如何重载相应的特殊方法(True&FalseFalse99&73,对于集合来说则是并集/交集...)。
    • 这也适用于其他一些语言,如Ruby、Perl和Javascript

但即使例如 a_boolean & another_boolean 的工作方式相同,正确的解决方案也是使用 and - 简单地因为 andor 与布尔表达式和条件相关联,而 &| 则代表位操作。


6
如果您想在numpy中进行逐元素布尔运算,则答案略有不同。您可以使用&|进行逐元素布尔运算,但andor会返回值错误。
为了安全起见,您可以使用numpy逻辑函数
np.array([True, False, True]) | np.array([True, False, False])
# array([ True, False,  True], dtype=bool)

np.array([True, False, True]) or np.array([True, False, False])
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

np.logical_or(np.array([True, False, True]), np.array([True, False, False]))
# array([ True, False,  True], dtype=bool)

4
一般规则是使用适当的运算符来操作现有的操作数。对于布尔(逻辑)操作数,使用布尔(逻辑)运算符,对于(更宽的)整数操作数,使用位运算符(注意:False等同于0,True等同于1)。唯一“棘手”的情况是将布尔运算符应用于非布尔操作数。 让我们举一个简单的例子:5 & 7 vs. 5 and 7。
对于位与(&),事情相当直接:
5     = 0b101
7     = 0b111
-----------------
5 & 7 = 0b101 = 5 (= 7 & 5)
对于逻辑运算符,这是[Python.Docs]: Boolean operations所述的(强调是我的):
请注意,andor都不限制它们返回的值和类型为False和True,而是返回最后一个被评估的参数。
示例:
>>> 5 and 7
7
>>> 7 and 5
5
同样适用于| vs. 或者,当然。

3
提示在名称中:
布尔运算符用于执行逻辑操作(在编程和形式逻辑中常见的真值测试)。
位运算符用于“位扭曲”(字节和数字数据类型中比特的低级操作)。
虽然使用位运算符进行逻辑操作是可能的,而且有时候确实是可取的(通常出于效率原因),但您应该通常避免这样做,以防止微妙的错误和不必要的副作用。
如果您需要操作位,则位运算符是专为此目的而构建的。 有趣的书籍:黑客的乐趣包含了一些很酷且真正有用的位操作示例。

1

布尔运算是逻辑运算。

按位运算是对二进制位的操作。

按位运算:

>>> k = 1
>>> z = 3
>>> k & z  
1
>>> k | z  
3

操作:

  • AND &:如果两个位都是1,则为1,否则为0
  • OR |:如果任一位为1,则为1,否则为0
  • XOR ^:如果两个位不同,则为1,如果相同则为0
  • NOT ~:翻转每个位

按位运算的一些用途:

  1. 设置和清除位

布尔运算:

>>> k = True
>>> z = False
>>> k & z  # and
False
>>> k | z  # or
True
>>> 

1
对于布尔运算,您是不是指的是“and”和“or”,而不是“&”和“|”? - Matthew Rankin
是的..是的..谢谢,我就是这个意思。 - pyfunc

0

布尔运算符 'and' 与位运算符 '&' 的区别:

伪代码/Python 帮助我理解了它们之间的差异:

def boolAnd(A, B):
    # boolean 'and' returns either A or B
    if A == False:
        return A
    else:
        return B

def bitwiseAnd(A , B):
    # binary representation (e.g. 9 is '1001', 1 is '0001', etc.)

    binA = binary(A)
    binB = binary(B)



    # perform boolean 'and' on each pair of binaries in (A, B)
    # then return the result:
    # equivalent to: return ''.join([x*y for (x,y) in zip(binA, binB)])

    # assuming binA and binB are the same length
    result = []
    for i in range(len(binA)):
      compar = boolAnd(binA[i], binB[i]) 
      result.append(compar)

    # we want to return a string of 1s and 0s, not a list

    return ''.join(result)

0

逻辑运算

通常用于条件语句。例如:

if a==2 and b>10:
    # Do something ...

这意味着如果两个条件(a==2b>10)同时为真,则可以执行条件语句体。

位运算

用于数据操作和提取。例如,如果您想提取整数的四个LSB(最低有效位),可以这样做:

p & 0xF

这个问题是关于Python的,但是答案似乎是用另一种语言编写的 - 也许是Ruby?无论如何,我已经修复了它。如果我漏掉了什么,请告诉我。 - wjandrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接