[英]Why is there a difference between `0--3//2` and `--3//2`?
我想知道如何在没有math
模块的情况下进行地板/天花板操作。 我通过使用 floor Division //
解决了这个问题,并发现负数给出了天花板。 所以这有效:
>>> 3//2
1
>>> -3//2
-2
显然,我希望答案是肯定的,所以首先我尝试了--3//2
,但这给出了 1。我推断这是因为 Python 评估--
为+
。 所以为了解决这个问题,我发现我可以使用-(-3//2))
,问题解决了。
但是我想到了另一个解决方案,即(我包含了前面的示例进行比较):
>>> --3//2 # Does not give ceiling
1
>>> 0--3//2 # Does give ceiling
2
我无法解释为什么包含 0 有帮助。 我已经阅读了关于除法的文档,但在那里我没有找到任何帮助。 我认为可能是因为评估顺序:
如果我使用--3//2
作为示例,则从文档中我可以看出Positive, negative, bitwise NOT
在此示例中, Positive, negative, bitwise NOT
是最严格的,我想这将评估--
为+
。 接下来是Multiplication, division, remainder
,所以我猜这是+3//2
其计算结果为1
,我们就完成了。 我无法从文档中推断出为什么包含0
改变结果。
参考:
Python 使用符号-
作为一元( -x
) 和二元( xy
) 运算符。 它们具有不同的运算符优先级。
具体来说,排序wrt //
是:
-
//
-
通过引入0
作为0--3//2
,第一个-
是二进制-
最后应用。 没有前导0
作为--3//2
,两者-
都是一元的并一起应用。
对应的求值/语法树大致是这样的,先求底部的节点在父节点中使用:
---------------- ----------------
| --3//2 | 0--3//2 |
|================|================|
| | ------- |
| | | 0 - z | |
| | -----+- |
| | | |
| -------- | ----+--- |
| | x // y | | | x // y | |
| -+----+- | -+----+- |
| | | | | | |
| ----+ +-- | ---+ +-- |
| | --3 | | 2 | | | -3 | | 2 | |
| ----- --- | ---- --- |
---------------- ----------------
因为一元-
一起应用,它们相互抵消。 相比之下,一元和二元-
分别在除法之前和之后应用。
这是一个简单的操作顺序问题。
--3//2
与(-(-3)) // 2
。 由于左侧没有任何内容,因此每个-
必须是一元否定; 这比//
具有更高的优先级; 所以3
被否定两次(产生 3)然后除以 2。
0--3//2
与0 - ((-3) // 2)
。 现在,有在左侧的东西,第一个-
一定是二进制减法,它的优先级比//
。 第二个-
仍然是一元否定; -3
除以2
产生-2
,然后从0
减去该值。
了解 CPython 实际计算方式的另一种方法是使用 dis 模块查看它实际使用堆栈机执行的操作。
>>> import dis
>>> dis.dis('0--3//2')
1 0 LOAD_CONST 0 (2)
2 RETURN_VALUE
哎呀,常量是在编译期间计算的,所以使用一个名称。
>>> t=3
>>> dis.dis('0--t//2')
1 0 LOAD_CONST 0 (0)
2 LOAD_NAME 0 (t)
4 UNARY_NEGATIVE
6 LOAD_CONST 1 (2)
8 BINARY_FLOOR_DIVIDE
10 BINARY_SUBTRACT
12 RETURN_VALUE
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.