Discussion:
[Tutor] revisiting a puzzle about -3**2 vs (-3)**2
D Wyatt
2015-08-12 16:07:01 UTC
Permalink
so I 'get' that -5**2 = -25 and (-5)**2 is 25, BUT if you write a function

def sq(x):
""" Output: sq returns the square of its input
input x: a number (int or float)
"""
return x**2

and pass it a negative number it handles it as though the argument is
in parentheses.

I find this confusing. Can someone explain?

Also, can someone please take me off moderated?

thanks in advance.
--
Deb Wyatt in WA
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Alan Gauld
2015-08-12 17:45:35 UTC
Permalink
Post by D Wyatt
so I 'get' that -5**2 = -25 and (-5)**2 is 25, BUT if you write a function
""" Output: sq returns the square of its input
input x: a number (int or float)
"""
return x**2
and pass it a negative number it handles it as though the argument is
in parentheses.
Of course it does.

x**2 => (x)**2

If you assigned a value to x like this:

x = -3
print x**2

You would expect it (I hope) to be treated as

print (x)**2

would you not?

That's what the function does.

Otherwise the function would, effectively,
have to do this, which would be very inconsistent.

if x < 0: return -(x**2)
else: return x**2

By passing a negative number (-3 say) into the function
you are effectively putting it in parens - you are saying
you want the square of -3

Neither are you passing in the string '-3' which then
gets pre-pended to '**2' and then evaluated.
You are passing in a single integer value.

It's the same with the builtin pow() function
Post by D Wyatt
pow(-3, 2)
9

I'm explicitly telling Python I want the value -3 raised
to the power 2.

If I write

-3**2

I'm telling Python to interpret the expression -3**2 according
to its language rules - which it does as -(3**2).
Post by D Wyatt
Also, can someone please take me off moderated?
Done :-)
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
D Wyatt
2015-08-12 19:14:16 UTC
Permalink
Post by Alan Gauld
pow(-3, 2)
9
I'm explicitly telling Python I want the value -3 raised
to the power 2.
Alan G
so passing any numeric expression in a function is like putting ()
around it, correct?

Thank you for demoderating me :).
--
Deb Wyatt in WA
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Steven D'Aprano
2015-08-13 01:31:26 UTC
Permalink
Post by D Wyatt
Post by Alan Gauld
pow(-3, 2)
9
I'm explicitly telling Python I want the value -3 raised
to the power 2.
Alan G
so passing any numeric expression in a function is like putting ()
around it, correct?
Hmmm. I suppose that in a manner of speaking the answer is Yes, but I
don't think that's a helpful way of looking at things. Or at least not
accurate.

Parentheses (round brackets) are used for various tasks in Python,
including calling functions and for grouping. (There are also others.)

When you say

pow(-3, 2)

the brackets () mean "call this function". The contents of the brackets
are treated as the arguments. In this case, the parsing rules used by
the Python interpreter treat the - sign as stronger than than comma, so
that it applies - to the 3. It has nothing to do with the brackets. One
might do this as well, with no brackets involved:

my_tuple = -3, 2

which gives a tuple of two values, minus-three and two, and NOT a tuple
of (3, 2) which then has the - operator applied to it. (That would cause
an error.)

When the parser splits apart each line of code to analyse it in
preparation for executing it, it has to decide in which order each
operation applies. Often that's just left-to-right, but operators can
change that, since we want mathematical expressions to match the rules
learned in maths class, not just left-to-right evaluation.

So each operator has a priority. The higher the priority, the earlier it
applies. If you dislike that precedence, the way to tell the interpreter
to use your own priorities is to group the terms in brackets first, just
like in maths class.

Multiplication has higher priority than addition, so:

1+2*3 == 7

not 9. If you want to do the addition first, you can write:

(1+2)*3 == 9

Exponentials have higher priority still:

2*3**2 == 18

and not 36, again just like maths class. The unary + and - operators
have quite low priority, but commas are even lower. (Technically, the
comma isn't actually considered an operator, but the difference is
subtle and doesn't really matter for this discussion.)

So the differences in behaviour between:

-3**2

(-3)**2

pow(-3, 2)

etc are all to do with the order of operations, not specifically the
parens. It just happens that parentheses can be used to change the order
of operations. Let's go through each it turn:

-3**2: since exponentiation ** has highest priority, that calculates as
3**2 gives 9, then apply the - sign to get -9.

(-3)**2: since brackets *used for grouping* are highest priority, that
calculates as 3, apply the - sign to get -3, raise to the power of 2 to
get 9.

pow(-3, 2): the brackets here are used for a function call, not
grouping. The parser effectively looks inside the brackets and splits on
commas, giving two expressions: "-3" and "2". The "-3" expression is
treated as 3, apply the minus sign to get -3, and the "2" expression is
obviously just 2.

So pow() receives two arguments, -3 and 2 exactly as you would
expect, and calculates -3 squared which is 9.

To check your understanding, can you predict what this will do?


x = 2
y = -2
print(x**3, y**3, -x**3, -y**3)


(Note that this time I am using cubes, not squares.)
--
Steve
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Emile van Sebille
2015-08-12 17:54:07 UTC
Permalink
Post by D Wyatt
so I 'get' that -5**2 = -25 and (-5)**2 is 25, BUT if you write a function
""" Output: sq returns the square of its input
input x: a number (int or float)
"""
return x**2
and pass it a negative number it handles it as though the argument is
in parentheses.
I find this confusing. Can someone explain?
the passed in number is a single object. But when parsing a line,
"-5**2", exponentiation happens first, then negation of the result. The
parens around the -5 force evaluation as a number.

Consider this:

def sq1(x):
sgn = int(x<0)
return sgn*abs(x)**2

That's effectively what the parser does.

Emile


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Válas Péter
2015-08-12 17:49:44 UTC
Permalink
Post by D Wyatt
so I 'get' that -5**2 = -25 and (-5)**2 is 25, BUT if you write a function
and pass it a negative number it handles it as though the argument is
in parentheses.
As the argument IS in parentheses. How do you pass it to the function
without parentheses?
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Continue reading on narkive:
Loading...