Why print(5 ** 2 ** 0 ** 1) = 5 in Python? - python

Can somebody explain me why Why print(5 ** 2 ** 0 ** 1) = 5 in Python?
I am trying to learn the language and somehow I am not quite sure how this math is done.
Thank you in advance.

Because, like many languages, the exponentiation operator binds right-to-left:
5 ** 2 ** (0 ** 1)
==
5 ** (2 ** 0)
==
5 ** 1
==
5

Exponentiation is right-associative, so your expression is the same as
5 ** (2 ** (0 ** 1))
== 5 ** (2 ** 0)
== 5 ** 1
== 5
where any integer raised to the zeroth power is 1 by definition.

Others have already pointed this out already, but I just wanted to mention the documentation. You can see this by typing help("OPERATORS") in your repl. There you will spot somewhere at the top:
Operators in the same box group left to right (except for exponentiation, which groups from right to left).
You are right to be surprised though, this seems like a very odd decision to me. In other languages, e.g. octave, 5 ^ 2 ^ 0 ^ 1 == 1 as you'd expect. Oddly enough, both Julia and R agree with python on this.
EDIT: On second thought, I suppose making exponentiation right-associative makes sense too; you would expect
to mean 5^8 rather than 25^3 ...
Incidentally, here's another trap. How much is: 5 * -1 ** 2 ? Is it 5 or -5?
See help("**") to see why it is what it is. (incidentally, this is how octave, R, and julia treat this case too).
The moral of the story is: always group when there is potential for ambiguity. Or at least check the precedence is what you think it is before ungrouping.

** is exponentiation.
0 raised to the power of 1 is 0. So, we could re-write the statement as print(5**2**0) without changing the result.
2 raised to the power of 0 is 1. So, we can re-write the statement as print(5**1) without changing the result.
5 raised to the power of 1 is 5. So, we can rewrite the statement as print(5) without changing the result.

Related

Basic operation giving different results in Python

I was playing around with few basic operations in Python 3 and came across this
Code 1:
a = 6
b = 3
a = a / 2 * b
print(a)
Output is 9.0
In one of the trainings I have seen that
a = a / 2
can be written as
a /= 2
So I re-wrote my above code as below
Code 2:
a = 6
b = 3
a /= 2 * b
print(a)
But now the output is 1.0.
I was expecting 9.0 as output. Can someone help me understand why code behaves this way?
In the case of a /= 2 * b, you saying that a will be divided by expression after /=.
In other words, your expression could be rewritten as a = a / (2 * b) where a = 6, b = 3
in
a /= 2 * b
the 2 * b is carried out first so if b == 3 it can be rewritten as:
a /= 6
That's because they perform operations in different order.
The first of block of code divides a (6) by 2 and then multiplies that result by b (3)
E.g. (6 / 2) * 3 = 9
However the second block of code does the following:
6 / (2 * 3) = 1
Note, that
a /= 2 * b
is basically
a = a / (2 * b)
The previous code is different. It's not like the above (look at the parentheses)
a = a / 2 * b
This is different than
a = a / (2 * b)
Because the first code interpret it as division and then multiply, while the second code interpret it as multiply (bottom) and then division.
as you can see in the documentatiopn on operator precedence * and / have the same precedence. two operations with the same precedence are executed from left to right:
Operators in the same box group left to right
so your first example is evaluated as
(a / 2) * b
the second as
a / (2 * b)
regarding your comment
a = a / 2 and a /= 2 are always equivalent, right?
for the built-in python numbers you are right.
for your own classes you can make the operations differ. if a is an insance of a custom class a/x will call __truediv__(self, other) while a/=x will call __itruediv__(self, other) as described in the data model.
I'm surprised none of the other answers mention this, but the reason doesn't have anything to do with math, order of operations or implicit parentheses.
x /= y is just another way of saying x.__itruediv__(y). Your second example is not equivalent to your first example, because parameters are evaluated before being passed in to a function call. So, a /= 2 * b is equivalent to a.__itruediv__(2 * b), and naturally, the expression 2 * b must be evaluated before being passed in to __itruediv__.

** operator behaving differently [duplicate]

What should print (-2 ** 2) return? According to my calculations it should be 4, but interpreter returns -4.
Is this Python's thing or my math is that terrible?
According to docs, ** has higher precedence than -, thus your code is equivalent to -(2 ** 2). To get the desired result you could put -2 into parentheses
>>> (-2) ** 2
4
or use built-in pow function
>>> pow(-2, 2)
4
or math.pow function (returning float value)
>>> import math
>>> math.pow(-2, 2)
4.0
The ** operation is done before the minus. To get the results expected, you should do
print ((-2) ** 2)
From the documentation:
Thus, in an unparenthesized sequence of power and unary operators, the operators are evaluated from right to left (this does not constrain the evaluation order for the operands): -1**2 results in -1.
A full detail of operators precedence is also available in the documentation. You can see the last line is (expr) which force the expr to be evaluated before being used, hence the result of (-2) ** 2 = 4
you can also use math library...
math.pow(-2,2) --> 4
-math.pow(2,2) --> -4
math.pow(4,0.5) --> 2
Python has a problem and does not see the -2 as a number. This seems to be by design as it is mentioned in the docs.
-2 is interpreted as -(2) {unary minus to positive number 2}
That usually doesn't give a problem but in -a ** 2 the ** has higher priority as - and so with - interpreted as a unary operatoe instead of part of the number -2 ** 2 evaluates to -2 instead of 2.

Why does Python take forever to evaluate 1**4**4**4**4?

I ran into a curious issue in both Python 2 and Python 3.
>>> 1**4**4**4
1L
which seems fine, but when I do this:
>>> 1**4**4**4**4
it swamps the CPU and never finishes.
Why?
I also ran these to see if it was something with the power function, or with the ** operator and it seems to be just the ** operator.
>>> (((((1**4)**4)**4)**4)**4)
1
>>> pow(pow(pow(pow(pow(pow(1,4),4),4),4),4),4)
1
>>> pow(pow(pow(pow(pow(pow(1.0,4),4),4),4),4),4)
1.0
>>> pow(pow(pow(pow(pow(pow(1L,4),4),4),4),4),4)
1L
>>> 1L**4**4**4
1L
I also tried another language and it seems to be just Python.
Why can't it evaluate this in microseconds? Can someone explain what it's doing with the CPU time?
Is there something non-intuitive about the order of operations that I am not understanding?
With the ** operator, the binding rules are such that in unparenthesized expressions the right-hand side is evaluated first.
Your 1 ** 4 ** 4 ** 4 ** 4 is evaluated in the following order:
1 ** (4 ** (4 ** (4 ** 4)))
and it is producing and allocating the memory for the huge number on the right that takes all the time:
>>> 4 ** 4 ** 4
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096L
>>> 4 ** 4 ** 4 ** 4
# ... wait a long time as Python allocates GBs of memory ...
Quoting the ** documentation:
Thus, in an unparenthesized sequence of power and unary operators, the operators are evaluated from right to left
Mathematically, exponentiation is right associative, so
1**4**4**4**4
is not the same as
(((((1**4)**4)**4)**4)**4)
Because it is not doing
(((((1**4)**4)**4)**4)**4)
It is doing
1**(4**(4**(4**(4**4))))
Note that the latter has to compute a HUGE number before simply raising 1 to that result.
Right associativity:
>>> 2 ** 2 ** 3
256
>>>
It's slow because it has to evaluate 4**4**4**4, which is does by multiplication to get the exact result.
(Don't forget that exponentiation is right-associative.)
P.S. 4**4**4 is 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096, so computing 4**4**4**4 by multiplication is going to take a very, very long time.

Could someone explain the logic here or what I am asking? (Boolean operations)

In Python 2.7
When asking the interpreter the following:
(1 or 3) > 2 it returns False
Why is this? What am I effectively asking the interpreter, apparently not if either 1 or 3 is greater than two.
Similarly, asking (1 or 5) in range(2,6) also returns False
I am 100% sure it has to do with my (x or y) part of the statement, but again, why is this? I do not so much need a different way of stating something like this, as I understand I could just ask:
if x in range(2,6) or y in range(2,6):
But I was just wondering why it does not work!
Let's examine (1 or 3) > 2:
(1 or 3) is evaluated first, giving 1 (see The Peculiar Nature of and and or if you're wondering why).
1 > 2 is evaluated next, giving False.
The correct way to express what you're trying to express is:
>>> 1 > 2 or 3 > 2
True
Another, more general, way is as follows:
>>> t = (1, 3)
>>> any(el > 2 for el in t)
True
Here, t can be any iterable.
1 corresponds to true. Thus the result for
1 or 3
is
1
and
1 > 2
is false.
And you could have known this if you had tried the answer for
1 or 3
in the shell.
That's not the proper use case for boolean operations. The first should be:
(1 > 2) or (3 > 2)
The expression:
(1 or 3) > 2
will first work out 1 or 3 then attempt to figure out if that is greater than two.
Similarly:
(1 or 5) in range(2,6)
is probably better expressed as either:
(1 in range(2,6)) or (5 in range(2,6))
or:
((1 >= 2) and (1 < 6)) or ((5 >= 2) and (5 < 6))
1 (understood as number) is evalued true (all numbers are evaluated to true, except 0), so there isn't the need to evalute 3 (understood as number).
This because you use an OR condition, that "stop" evaluation onto first true value that find.
So, is 1 > 2? The answer is false
You have to decompose or if into two separate condition:
1 > 2 or 3 > 2
I'm gonna throw my two cents into this question as well.
When Python evaluates your statement
(1 or 3) > 2
This is what it does, Hey! Let's take first number and call bool() on it. Any number here that isn't 0 will be evaluated to True and return that.
You can try (10000 or 3), it will always return the most left hand "variable" as long its not 0
Example of the opposite would be if you had
(0 or 3)
It then goes on to evaluate the rest of the expression, which basically will say in pseudocode:
returned number (wheter its the left or right) is greater than 2
And this is where it gets weird, your expression will always then differ because of how the parenthesis was evaluated.
In your case it'll be
1 > 2 == False but (0 or 3) > 2 == True
As for the range part, the same logic applies.
In the parenthesis the left hand number will be "returned" and thusly, wont be available in your range check.
(1 or 4) in range(2,5) == False

Python integrals

I'm trying to solve the integral of (2**(1/2)*y**(1/2)/2)**2 from 0 to 5 (also shown here). I've been using
func = lambda y: ( 2**(1/2) * y**(1/2)/2 )**2 and a == 0 and b == 5
from scipy import integrate
integrate.quad(func, a b)
For some reason, I keep getting the value 1.25, while wolfram says it should be 6.25? I can't seem to put my finger on the error.
p.s. sorry for the error katrie, i forgot that python uses and not && for logical AND
SOLVED:
this was a silly int/float error. thank you everyone.
Well, let me write your function in normal mathematical notation (I can't think in Python). I don't like **, as it gets confusing:
(2**(1/2)*y**(1/2)/2)**2 =>
(2^(1/2) * (1/2) * y^(1/2))^2 =>
2 * (1/4) * y =>
y / 2
So to integrate, antidifferentiate (I'm just thinking aloud):
antidifferentiate(y / 2) = y^2 / 4
Therefore
integral('y / 2', 0, 5) =
5^2 / 4 - 0^2 / 4 =
25 / 4 =
6.25
Right. Have you tried replacing 1/2 with 0.5? It could be interpreted as the quotient of two integers, which is rounded up.
Try this (as the others have suggested):
func = lambda y: (2**(0.5) * y**(0.5) / 2.0)**2.0 & a == 0 & b == 5
from scipy import integrate
integrate.quad(func, a b) # What's 'a b'? Maybe 'a, b' would work?
Good luck!
The problem is that Python sees (1/2) and evaluates it with integer division, yielding zero.
Well what's the value supposed to be? Also, you should put more parenthesis in your equation. I have no idea what (2**(1/2)*y**(1/2)/2)**2 gets parsed out to be.

Categories

Resources