不明白为什么 (5 | -2) > 0 是 False 其中 (5 or -2) > 0 是 True

Don't understand why (5 | -2) > 0 is False where (5 or -2) > 0 is True

这是一个非常琐碎的问题,我一直无法找到答案。

问题来了。我有以下数组:

vals = [-5, 2]

我想检查val[0]val[1]是否大于0。如果其中一个为真,那么我应该输出True。

我的直接想法是使用; (vals[1] or vals[0]) > 0) 但我发现 (5 | -2) > 0 是错误的,而 (5 or -2) > 0 是正确的

任何澄清将不胜感激。

or|有什么区别?

or 是逻辑或,| 是按位或逻辑包含或。

逻辑或

The logical or in python returns the first value that is true.

示例:

>>> None or False or 5
5
>>> -5 or 2
-5

按位或逻辑包含或

按位或逻辑包含或由 python 中的 | 运算符表示并创建 number where all bits are set that are set in at least one of the given numbers.

示例:

  • 2 是二进制 0010
  • 4 是二进制 0100

两者之间的逻辑或结果 0110 为 6。

>>> 2 | 4
6

如何存储负数通常是特定于实现的。然而,在大多数系统上,通过反转每个位并加 1 创建正数的 two's complement 来存储负数。

该数字按位运算两个任何其他数字仍会产生负数:

>>> -5 | 2
-5

两者都不能解决你的问题

同时使用

(vals[1] or vals[0]) > 0

似乎有效,当你翻转值时它失败了:

>>> vals = [2, -5]
>>> (vals[1] or vals[0]) > 0
False

您应该分别检查两个值

>>> vals = [-5, 2]
>>> vals[0] > 0 or vals[1] > 0
True

对于较大的输入,这可能不方便。您应该将 any 与生成器表达式一起使用:

>>> any(x > 0 for x in vals)
True

您需要 any 函数:

>>> any(x > 0 for x in vals)

x | y 计算两个值的按位 OR,而 x or y 计算第一个 "truthy" 值。在这两种情况下, 结果 然后与 0 进行比较:(x or y) > 0(x | y) > 0.

您想将每个值与零(必要时)与

进行比较
vals[0] > 0 or vals[1] > 0

如果你有三个值,你会写

vals[0] > 0 or vals[1] > 0 or vals[2] > 0

any 函数将其泛化为任意大小的列表,而不需要根据列表的大小来决定 or 有多少项在一起。

当您执行 (5 | -2) 时,您正在执行按位或运算。这将保留数字中的否定位。因此,您仍然会得到一个负数。

(5 or -2) 是逻辑或,Python 解释器会将其扩展到下一个逻辑运算符(大于)。

它们是两个完全不同的操作,所以这是意料之中的。

为了说明,这里有一个小 shell 日志:

In [1]: 5 or -2
Out[1]: 5

In [2]: 5 | -2
Out[2]: -1

or运算符returns第一个非零(非None、非False等)值。

| 运算符执行按位或。举例说明:

In [3]: bin(5)
Out[3]: '0b101'

In [4]: bin(-2)
Out[4]: '-0b10'

In [5]: bin(5 | -2)
Out[5]: '-0b1'

| 是整数的 bitwise OR, and Python uses two's complement 表示。评估 5 | -2 给出:

  ... 0000 0000 0000 0101 (+5)
| ... 1111 1111 1111 1110 (-2)
──────────────────────────────
= ... 1111 1111 1111 1111 (-1)

并且-1不大于零,所以(5 | -2) > 0为假。

or 是逻辑或。与此运算符 returns 布尔值 (True/False) 值的其他语言不同,Python 将 x or y 定义为等同于 x if x else y(除了仅计算 x一次)。请注意,任何非零数值在 Python 中都是“真实的”,因此如果 x≠0,则 x or y 的计算结果为 x.

>>> 5 or -2
5
>>> -2 or 5
-2

(5 or -2) > 0 的计算结果为 True 是幸运的,因为它首先是正数。在另一个顺序中,你会得到 False。

一般来说 (x or y) > 0 等同于 (x > 0) or (y > 0),这就是你的意思。

要回答这个问题,我必须解释一下补码。

数字的二进制表示

所以你知道在内部,像 5 这样的整数是如何表示为二进制字符串的

00000000000000000000000000000101

你认为你会如何表示一个负数?

好吧,这就是我们想要做的:

  • 加法对于负数和正数应该是一样的;也就是说,您执行相同的步骤将 4 + 9 添加为 4 + -9.

  • 整数溢出不应该破坏数学;即 MAX_VALUE + 1 == MIN_VALUEMIN_VALUE - 1 == MAX_VALUE

所以我们做的事情叫做"Two's Complement."

补码

表示一个负数,取它的绝对值,bitflip每一位,然后加1。

所以如果正数是5

00000000000000000000000000000101

负数-5是

11111111111111111111111111111011

本质上,这意味着我们选择数字01111111111111111111111111111111作为最大的正数,并且之后的所有数字都是负数。

那么 (5 | -2) 是什么意思?

|是按位或运算符。给定两个数字,它将每个位和或将它们组合在一起,构造一个新数字,其中如果在凋零中该位置的数字或两个原始数字中的两个数字都为 1,则该数字为 1,否则为 0。计算结果如下:

   5 -> 00000000000000000000000000000101
| -2 -> 11111111111111111111111111111110
----    --------------------------------
        11111111111111111111111111111111 -> -1

如你所见,5 | -2 = -1 < 0.

关于(5 或 -2)呢?

"or" 运算符有两个值,将它们转换为布尔值 并将它们组合在一起。这很重要:它不是或值,它 returns 第一个值是 "truthy" ——换句话说,如果你把它放在 if 语句中,它会 运行 .

唯一不是"truthy"的整数是0。因此(5或-2)returns5和2的第一个非零整数,即5>0。所以5 或 -2 = 5 > 0.