Why Is Exponentiation Applied Right to Left

Why is exponentiation applied right to left?

The ** operator follows normal mathematical conventions; it is right-associative:

In the usual computer science jargon, exponentiation in mathematics is right-associative, which means that xyz should be read as x(yz), not (xy)z. In expositions of the BODMAS rules that are careful enough to address this question, the rule is to evaluate the top exponent first.

and from Wikipedia on the Order of Operations:

If exponentiation is indicated by stacked symbols, the usual rule is to work from the top down, because exponention is right-associative in mathematics.

So 2 ** 3 ** 4 is calculated as 2 ** (3 ** 4) (== 2417851639229258349412352) not (2 ** 3) ** 4 (== 4096).

This is pretty universal across programming languages; it is called right-associativity, although there are exceptions, with Excel and MATLAB being the most notable.

Negative numbers with exponents in Python

Python parses print(-1**2) in the following order:

  1. Get's the exponent of 1 ** 2

  2. Negates the result.

So it becomes this:

>>> -(1 ** 2)
-1
>>>

Because -1 translates to print(0 - 1 ** 2). But in the order of operations table, ** (exponents) is higher ranking than -.

Therefore, Python math follows the order of operations in regular math, ** is more powerful (has more priority over) -.

As mentioned on Wikipedia:

The acronym PEMDAS is common. It stands for Parentheses, Exponents, Multiplication/Division, Addition/Subtraction.

Also mentioned on the Python Docs:



































OperatorDescription
(expressions...), [expressions...], {key: value...}, {expressions...}Binding or parenthesized expression, list display, dictionary display, set display
x[index], x[index:index], x(arguments...), x.attributeSubscription, slicing, call, attribute reference
await xAwait expression
**Exponentiation
+x, -x, ~xPositive, negative, bitwise NOT
*, @, /, //, %Multiplication, matrix multiplication, division, floor division, remainder 6

Is Groovy Power Operator (**) Broken in Associativity?

No, it's not broken

It just has left to right associativity as with all other operators

In python ** has right to left associativity, so that's not broken either

They just have different rules

What are the ramifications of right-to-left and left-to-right associativity in C based languages?

For the most part, each operator has the associativity that makes the most sense for that operator.

All of the non-assignment binary operators have left-to-right associativity. This is useful for the obvious reason that English is read left-to-right and thus the evaluation of x + y + z is consistent with how it is read. In addition, for arithmetic operators, the semantics match what we expect from the usage of the operators in mathematics.

Assignment operators have right-to-left associativity. Left-to-right assignment would have bizarre and unexpected semantics. For example, x = y = z would result in x having the original value of y and y having the original value of z. It is expected that all three variables will have the same value after the expression is complete.

The prefix unary operators have right-to-left associativity, which makes sense because the operators closest to the operand are evaluated first, so in ~!x, !x is evaluated first, then ~ is applied to the result. It would be really, really weird were prefix operators applied with left-to-right associativity: to say that ~!x means evaluate ~x and then apply ! to the result is the complete opposite of how we think about expressions (or, at least, how most people think about expressions...).

Explanation of right to left binary method of modular arithmetic?

This algorithm is a combination of the Exponentiation by Squaring algorithm and modulo arithmetic.

To understand what's going on, first consider a situation when exponent is a power of 2. Then, assuming that exponent = 2 ^ k, the result could be computed by squaring the result k times, i.e.

res = (...((base ^ 2) ^2 ) ... ) ^2))
---------------------
k times

When exponent is not a power of 2, we need to make additional multiplications. It turns out that if we can divide exponent by 2 without remainder, we can square the base, and divide the exponent. If, however, there is a remainder, we must additionally multiply the intermediate result by the value of the current base.

What you see is the same exponentiation by squaring applied to modulo multiplication. The algorithm denotes integer division by two using the exponent >> 1 operation, which is identical to floor(exponent / 2).

Order of calculation

Your teacher is wrong. From https://docs.python.org/3/reference/expressions.html#evaluation-order:

6.15. Evaluation order

Python evaluates expressions from left to right. Notice that while
evaluating an assignment, the right-hand side is evaluated before the
left-hand side.

The * has two expressions as its operands, 10**4 and 3**2. The left operand, 10**4 is evaluated first, followed by the right operand, 3**2.

Your teacher may be confused with a chain of exponentiations like 2 ** 3 ** 4. Here the "outer" exponentiation has two arguments 2 and 3 ** 4 (rather than 2**3 and 4, because of right associativity). However, the 2 is still evaluated before 3**4.

For a simple expression like this, it doesn't really matter. But it could matter if one or both operands involved function calls with side effects. Consider something contrived like lambda: print(3) or 3)() + (lambda: print(4) or 4)(). The value of the expression is 7 either way, but the order in which the print functions are called will affect the output. Python, though, guarantees that 3 will be output before 4.


Some languages (notably C, IIRC) don't specify an order of evaluation, so it is an implementation detail whether the left or right is evaluated first. This means you can't predict the value of something like i=3; j=(i++)*i; j could be either 3*3 == 9 or 4*3 == 12, depending on whether i is incremented before or after the right-hand operand is evaluated. (I don't recall if this is considered undefined behavior or implementation-defined behavior, though.)



Related Topics



Leave a reply



Submit