【问题标题】:Don't understand why (5 | -2) > 0 is False where (5 or -2) > 0 is True [duplicate]不明白为什么 (5 | -2) > 0 为假,其中 (5 或 -2) > 0 为真 [重复]
【发布时间】:2019-08-09 00:22:03
【问题描述】:

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

这就是问题所在。我有以下数组:

vals = [-5, 2]

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

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

任何澄清将不胜感激。

【问题讨论】:

标签: python conditional


【解决方案1】:

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

【讨论】:

  • 这些是 Python 整数,而不是原生 CPU 整数;我很确定他们明确指定使用二进制补码。 (也就是说,我很难找到这样的规范。我发现最接近的是this wiki page,它足够明确但可能不完全权威,an oblique remark in the docs 说“@ 的按位反转987654343@ 定义为-(x+1)。")
  • 是的,docs for the built-in types 有几个提示。
  • 很好的发现。事实上,该页面明确表示“按位运算的结果是按照二进制补码计算的,具有无限数量的符号位。”
【解决方案2】:

你想要any函数:

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

x | y 计算两个值的按位 OR,而 x or y 计算为第一个“真实”值。在这两种情况下,结果都会与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 共有多少项。

【讨论】:

    【解决方案3】:

    要回答这个问题,我必须解释一下Two's Complement。

    数字的二进制表示

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

    00000000000000000000000000000101
    

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

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

    • 加法应该对负数和正数起作用;即您执行相同的步骤将 4 + 9 添加为 4 + -9。

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

    所以我们所做的就是所谓的“Two's Complement”。

    两个的补码

    表示一个负数,取其绝对值,每一位翻转,加1。

    所以如果正数是5

    00000000000000000000000000000101
    

    负数-5是

    11111111111111111111111111111011
    

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

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

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

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

    如您所见,5 | -2 = -1

    怎么样(5 或 -2)?

    “或”运算符接受两个值,将它们转换为布尔值,然后将它们组合在一起。这很重要:它不返回值,而是返回第一个“真实”值——换句话说,如果你把它放在 if 语句中,它就会运行。

    唯一不是“真实”的整数是 0。因此(5 或 -2)返回 5 和 2 的第一个非零整数,即 5 > 0。所以 5 或 -2 = 5 > 0 .

    【讨论】:

    • 上学学 CS 的时候真的很有用,不是吗?很好,完整的答案。欢迎来到 SO!
    • 精彩的解释!缺少一件事;你是怎么做 OP 想要的?
    • 您可以说 vals[0] > 0 或 vals[1] > 0,这可能最适合作为辅助函数:
    • def atLeastOnePositive(vals): for val in vals: if val > 0: return True
    • return False # 在for循环之外,如果没有元素> 0
    【解决方案4】:

    |bitwise OR,Python 使用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 是逻辑或。与此运算符返回布尔 (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),这就是你的意思。

    【讨论】:

    • 我觉得自己很笨,但是为什么所有1s 都等于-1 而不是2^16 之类的?
    • @user1717828 因为通常的约定是将最高有效位视为负数;所以 -2^31 是一个 4 字节的整数。这允许存储良好范围的正数和负数。如果所有位都被视为正数,则您只能表示正数,这在许多情况下会不太有用。
    • 另外,Python 将这一点发挥到了极致; -11s 的无限个数 表示。 (它被压缩在内存中,在 CPython(参考)实现中。)
    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

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

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

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

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

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

      In [3]: bin(5)
      Out[3]: '0b101'
      
      In [4]: bin(-2)
      Out[4]: '-0b10'
      
      In [5]: bin(5 | -2)
      Out[5]: '-0b1'
      

      【讨论】:

        猜你喜欢
        • 2021-05-25
        • 2020-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 1970-01-01
        • 2018-05-01
        相关资源
        最近更新 更多