Power operator (^) precedence levels and evaluation order

20 views (last 30 days)
While
2^-1^-2
returns 4, which indicates a "left to right" evaluation order (as it is common in many programming languages),
2^-1^-2^3
returns 0.125, which I find surprising – I would have expected a value of 4^3 = 64.
To examine the order applied by Matlab, I tried all possible combinations:
((2^-1)^-2)^3 % returns 64 (1st, then 2nd operator)
(2^-1)^-(2^3) % returns 256 (1st and 3rd)
(2^-(1^-2))^3 % returns 0.125 (2nd, then 1st)
2^-((1^-2)^3) % returns 0.5 (2nd, then 3rd)
2^-(1^-(2^3)) % returns 0.5 (3rd, then 2nd)
So it seems that Matlab first evaluates the 2nd operator, then the 1st (=left), then the 3rd (=rightmost). That seems very odd. Can anybody explain why Matlab chooses this evaluation order?
I'm aware of https://de.mathworks.com/help/matlab/matlab_prog/operator-precedence.html, but it just doesn't make sense to me. According to the rules given there, the 3rd operator (^) in my example should even come first, as it has a higher precedence than the other two (^-) operators. So doesn't Matlab adhere to its own rules?
  18 Comments
dpb
dpb on 24 Jun 2024
It will be most interesting to hear the result...
creepydog
creepydog on 28 Jun 2024
TMW has answered my support request (see accepted answer), which referred to this thread but contained its own example and focus. The answer isn't 42, but the corresponding question shouldn't be unknown anyway. So, for completeness and transparency, I'd like to post the full text of my support request here:
<quote>
If you run this expression in the Command Window:
>> 2^+3^2
Matlab returns ans = 64, which shows that it was evaluated from left to right, i.e. as (2^+3)^2. Otherwise the result would be 512.
The operator precedence documentation [1] says that there are two different precedence levels for power operators (levels 2 and 3). The normal matrix power operator ^ has precedence level 2, while the "matrix power with unary plus" operator ^+ has level 3, which is inferior to level 2. So, according to the documentation, 2^+3^2 should be evaluated as 2^+(3^2), because the ^ operator has higher precedence than ^+ (like 2+3*4 is 14, not 20).
There's a note in the documentation [1] saying that level 3 operators deviate from the normal left-to-right rule [2], but that only matters within (!) this precedence level 3. Operators of precedence level <= 2 still have priority over operators of level 3, so ^ must precede ^+ according to the documentation, regardless of left/right aspects.
Please also see my question and the discussion with/of several MVPs in Matlab Central [3] for more examples and thoughts about this problem.
[2] They "work from second from the right to left", I'm not sure what that means, linguistically.
</quote>

Sign in to comment.

Accepted Answer

Oliver Jaehrig
Oliver Jaehrig on 28 Jun 2024
The statement below is coming from our development team and they reviewed the discussion on MATLAB Answers and the incoming support request regarding it:
We agree that the current behavior is unusual. Unfortunately, it's decades-old MATLAB behavior. We may choose to change it, but it cannot change suddenly without adequate notice.
We strongly recommend using parentheses to clarify the intended order of operations. The Code Analyzer suggests this, and early versions of MATLAB actually required this.
To clarify what is meant by "second from the right to left" in the doc,
a^-b^-c^-d^-e^-f
is parsed as
(a ^ (- (b ^ (- (c ^ (- (d ^ (- e)))))))) ^ (- f)
which is essentially equivalent to
X1 = -(d^-e);
X2 = -(c^X1);
X3 = -(b^X2);
X4 = a^X3;
X5 = X4^-f
Our development team considers to enhance the documentation about this in a future release. If there are any further questions, please let me know, or create a new support request if needed.
  18 Comments
Julian Hapke
Julian Hapke on 21 Jul 2024
Edited: dpb on 21 Jul 2024
You can see how MATLAB evaluates an expression by using the mtree function. It does indeed not recognize ^+ as it's own operator, but as soon as there is a unary operator inside an exponent, it influences the abstract syntax tree of the whole expression, e.g.:
```
dump(mtree('5 ^ 4 ^ 3 ^ 2'))
1=== * PRINT: 1/11
2=== * EXP: 1/11
3=== * EXP: 1/07
4=== * EXP: 1/03
5=== * INT: 1/01 (5)
6=== * INT: 1/05 (4)
7=== * INT: 1/09 (3)
8=== * INT: 1/13 (2)
dump(mtree('5 ^+ 4 ^ 3 ^ 2'))
1=== * PRINT: 1/12
2=== * EXP: 1/12
3=== * EXP: 1/03
4=== * INT: 1/01 (5)
5=== * UPLUS: 1/04
6=== * EXP: 1/08
7=== * INT: 1/06 (4)
8=== * INT: 1/10 (3)
9=== * INT: 1/14 (2)
```
5 ^ 4 ^ 3 ^ 2 == (((5 ^ 4) ^ 3) ^ 2)
and
5 ^+ 4 ^ 3 ^ 2 == (5 ^+ (4 ^ 3)) ^ 2
dpb
dpb on 21 Jul 2024
Interesting, thanks! I was not aware of mtree after 30 years...

Sign in to comment.

More Answers (0)

Categories

Find more on Fortran with MATLAB in Help Center and File Exchange

Products


Release

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!