views:

226

answers:

5

I was just bitten by the following scenario:

>>> -1 ** 2
-1

Now, digging through the Python docs, it's clear that this is intended behavior, but why? I don't work with any other languages with power as a builtin operator, but not having unary negation bind as tightly as possible seems dangerously counter-intuitive to me.

Is there a reason it was done this way? Do other languages with power operators behave similarly?

+20  A: 

That behaviour is the same as in math formulas, so I am not sure what the problem is, or why it is counter-intuitive. Can you explain where have you seen something different? "**" always bind more than "-": -x^2 is not the same as (-x)^2

Just use (-1) ** 2, exactly as you'd do in math.

nosklo
@nosklo - Personally, I'd disagree. I'll typically interpret -x^2 as being (-x)^2 *unless* you're subtracting. So 1-x^2 would be 1 + -(x^2)
Jason Baker
@Jason: go read your pre-algebra book again... that's not how math works.
rmeador
@Jason, you may disagree but that's the standard that mathematicians have settled on.
David Locke
I agree that -x^2 should be -(x^2), but for constants, I feel like -1^2 should parse as (-1)^2. Unfortunately, -1 is not parsed as a single token of a constant -1, but rather as the unary negation operator on the constant 1.
Adam Rosenfield
there's a shift-reduce conflict that you chose how to solve, depending on your rule to resolve conflict, you may find counter-intuitive or not...
LB
Well, that's certainly an excellent reason. I suppose I've just been out of school for too long!
Ben Blank
for the same reason 10-8/2 = 6 and not 1, in fact in math you see it like 10-(8/2) and not like (10-8)/2. In your case power priority is higher than sum (or sub) priority and python (correctly) read -1**2 as -(1**2) and not as (-1)**2
Andrea Ambu
@Andrea Ambu — That's what got me; I'm usually good at precedence. In fact, I think this is the first order-of-operations problem I've had in a couple of decades! :-)
Ben Blank
+3  A: 

If I had to guess, it would be because having an exponentiation operator allows programmers to easily raise numbers to fractional powers. Negative numbers raised to fractional powers end up with an imaginary component (usually), so that can be avoided by binding ** more tightly than unary -. Most languages don't like imaginary numbers.

Ultimately, of course, it's just a convention - and to make your code readable by yourself and others down the line, you'll probably want to explicitly group your (-1) so no one else gets caught by the same trap :) Good luck!

Mike
+4  A: 

Short answer: it's the standard way precedence works in math.

Let's say I want to evaluate the polynomial 3x**3 - x**2 + 5.

def polynomial(x):
    return 3*x**3 - x**2 + 5

It looks better than...

def polynomial
    return 3*x**3 - (x**2) + 5

And the first way is the way mathematicians do it. Other languages with exponentiation work the same way. Note that the negation operator also binds more loosely than multiplication, so

-x*y === -(x*y)

Which is also the way they do it in math.

Dietrich Epp
The binary subtraction example seems irrelevant. The unary minus example with multiplication is more valuable.
S.Lott
A: 

Ocaml doesn't do the same

# -12.0**2.0
  ;;
- : float = 144.

That's kind of weird...

# -12.0**0.5;;
- : float = nan

Look at that link though... order of operations

LB
Ocaml is broken. It doesn't follow this basic math rule.
nosklo
+1  A: 

It seems intuitive to me.

Fist, because it's consistent with mathematical notaiton: -2^2 = -4.

Second, the operator ** was widely introduced by FORTRAN long time ago. In FORTRAN, -2**2 is -4, as well.

Igor Krivokon