无法理解 ** 运算符的行为

3

我突然遇到了这个问题,不明白为什么会发生这种情况!

在Python提示符上,使用**操作符对3及以上的数字进行运算时,会得到错误的结果。例如:

>>> 2**2**2
16
>>> 3**3**3
7625597484987L
>>> 4**4**4
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096L

然后我想我必须使用括号,所以我使用了它,现在得到了正确的结果。

>>>(3**3)**3
19683

但是//操作符也支持并且在这种情况下给出了正确的结果。

>>> 4//4//4
0
>>> 40//4//6
1

请帮我理解。


2
你期望 4 ** 256 返回什么? - Rohit Jain
2
如果 ** 的行为符合文档,请始终查阅文档以获取意外行为的解释。请参考 http://docs.python.org/3.1/reference/expressions.html 中的第5.4节。 - Andrew Morton
感谢提供文档链接。我现在已经明白了。 - Tanmaya Meher
4个回答

9

** 是右结合的。从数学角度来看,这是有意义的:333 等于 327,而不是 273

文档指出,它是右结合的:

在未加括号的幂和一元操作符序列中,操作符从右到左进行求值。


实际上,我认为文档中的这行内容只是在澄清该部分中的幂运算符与一元运算符规则以及5.15节中幂运算符和比较运算符的右结合规则之间的交互作用。但我不确定。无论如何,这可能是文档中最清晰的陈述,告诉操作员应该期望看到他正在看到的内容。 - abarnert
@abarnert:是的,正如你所说,那行文档并不具有权威性。它只是一种总结语法定义含义的方式。 - nneonneo
1
我认为这是在文档的第5.4节中,标题为“幂运算符”的第二段(示例后面)。它写道:“因此,在未加括号的幂和一元运算符序列中,运算符从右到左进行评估(这不限制操作数的评估顺序):-1 ** 2的结果为-1。” - Tanmaya Meher

3
正如文档所述:

相同优先级的运算符从左到右分组(除了比较...和指数,后者从右到左分组)。

换句话说,**是右结合的,而//(像所有其他运算符一样,除了比较运算符)是左结合的。
在其他地方,有一个关于幂运算符的整个部分,在给出一个规则(这里不相关)关于幂运算符和一元运算符如何交互之后,澄清道:

在未加括号的幂和一元运算符序列中,运算符从右向左计算...

这实际上是大多数编程语言的方式。
幂运算在数学中没有对称的运算符语法,因此它没有理由具有相同的默认结合性。并且右结合的幂运算远不如左结合的幂运算有用,因为(2**3)**42**(3*4)完全相同,而2**(3**4)没有明显的相同之处。

我认为你的意思是“-结合的指数运算符没有太多用处”。 - nneonneo

1

看起来 ** 运算符是右结合的,这意味着 3**3**3 的计算结果为 3**27,而 4**4**4 的计算结果为 4**256


非常感谢。但是,“//”运算符必须是左结合的吗? - Tanmaya Meher
我不知道 // 运算符应该做什么,但如果它返回正确的结果,那么是的。 :) - cHao
“//” 是地板除法运算符。它是左结合的(这很有道理,因为在算术上 10/5/2 == 1 而不是 4)。 - nneonneo

1
当你做类似 4**4**4 的事情时,应该使用括号来明确你的意图。解析器会消除歧义,正如 @cHao 所示,但这会让其他人感到困惑。你应该使用 (4**4)**4 或者 4**(4**4)。在这里明确比隐含更好,因为对幂次方的操作并不是我们经常看到的日常操作。

是的,我当然明白我必须使用括号,但只是想知道一下,而且我也看到了 ** 和 // 之间的区别,所以就好奇了!无论如何,非常感谢。 - Tanmaya Meher

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