Why does `-(num)**(even_number)` give `-(num^(even_number))` as result? - python

This is something weird I noticed.
Any particular reason why -5**2 gives -25 and math.pow(-5,2) gives 25? The answer should be 25. So what is the reason for the -25 answer?
>>> -5**2
-25
>>> -5**4
-625
>>> 5**2
25
>>> 5**4
625
>>> import math
>>> pow(-5,2)
25
>>> pow(-5,4)
625
>>>

In Python the ** operator has higher precedence than the - operator, so in your expression 5 ** 2 is evaluated first, then negated. You can apply negation first by using brackets:
>>> -5**2
-25
>>> (-5)**2
25

This is all explained in the documentation
The power operator binds more tightly than unary operators on its left; it binds less tightly than unary operators on its right.
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.

The documentation for math.pow specifies that it raises x to the power of y.
So, math.pow calculates (-5)**4. whereas just writing -5**4 is equivalent to -1 * 5 **4, since by operator precedence in Python the unary operator - has less precedence than the power operator **.

This is because of the operator precedence in python.
If we look at the operator precedence, we see that the unary operator -x has lower precedence than the power operator x**y, so that the expression -5**2 means to first apply the square to the 5 and then apply the negative sign to the result. This first operation gives 25, which then gives -25.
The expression math.pow(-5,2) means to square the -5. This is equivalent to (-5)**2.

It's because of that the precedence of - operator is lower than power operator **. In fact your expression will be calculated as following:
>>> -(5 ** 2)
Try the following to get the correct result:
>>> (-5) ** 2
25
For more information you can read the python Operator precedence:
The following table summarizes the operator precedence in Python, from lowest precedence (least binding) to highest precedence (most binding).

Related

Order of calculation

Example : 10 ** 4*3 ** 2
Our teacher said python first calculates 3**2 and then 10**4 and then multiplies the answers.
But if both side of the multiplication have same order of precedence and python reads from left to right, doesn’t it do 10**4 first and then 3**2?
(My question is not about the order or precedence of operations as both side have same order of precedence)
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.)
We can easily test it:
class C:
def __init__(self, v):
self.v = v
def __pow__(self, x):
print(f'eval {self.v} ** {x}')
return self.v ** x
>>> C(1) ** 2 * C(4) ** 5
eval 1 ** 2
eval 4 ** 5
1024
In short, your teacher is wrong, at least for Python 3.7. In any case, regardless of whether it's true, I'd never rely on the order here, since those assumptions make the code less readable.

Built in double-asterisk power function not working as expected [duplicate]

This question already has answers here:
Calculation error with pow operator
(4 answers)
Closed 5 years ago.
This prints -2.4:
print(-3**0.8)
But this prints an imaginary number...?
a = -3
b = 0.8
print(a**b)
I can't figure out what is causing this and this problem is breaking my program. How do you make it so that the second statement outputs the same as the first in a general case that works for positive and negative values for a?
Per the Python 3.6 documentation:
6.5. The power operator
The power operator binds more tightly than unary operators on its left; it binds less tightly than unary operators on its right. The syntax is:
power ::= ( await_expr | primary ) ["**" u_expr]
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.
Thus, in the first example:
>>> -3 ** 0.8
-2.4082246852806923
It's evaluated right to left as ** has higher precedence than unary -, binding tighter -- so here, 3 ** 0.8 is evaluated first, then the unary - operator is applied for a negative value. In the second example however, the expression is equivalent (-3) ** 0.8 as -3 is stored in a name, and evaluation results is an imaginary number:
>>> a = -3
>>> b = 0.8
>>> a ** b
(-1.9482946966653392+1.4155189542146738j)
A solution would be to calculate the result without unary operators, then applying a sign as necessary, per Shakar Bhattarai's answer:
>>> int(a / abs(a)) * (abs(a) ** b)
-2.4082246852806923
The first part, int(a / abs(a)) evaluates to either -1.0 or 1.0 depending on if a is negative or not, basically applying the sign. It then multiplies that by the result of a ** b regardless of a's sign. That will first compute a ** b disregarding it's sign, then applying the sign as necessary. This will get rid of the discrepancy. You could apply the same concept with math.copysign:
>>> math.copysign(1, a) * (abs(a) ** b)
-2.4082246852806923
This will just copy the sign from a to 1, which will give -1.0 or 1.0 based on negativity.
This is because of the precedence of the power operator. The power operator binds tighter than unary operators. So:
-3 ** 0.8
is evaluated as
-(3 * 0.8)
You can see how Python parses your code using the ast module:
>>> import ast
>>> ast.dump(ast.parse('-3 ** 0.8'))
'Module(body=[Expr(value=UnaryOp(op=USub(), operand=BinOp(left=Num(n=3), op=Pow(), right=Num(n=0.8))))])'
>>>
In the above, the 3 ** 0.8 is treated as one expression with ** being the operator. The unary minus is then applied to the value of the inner expression.
However, in your second example the values are stored in variables, so the precedence does not affect the expression. So a ** b is equivlent to (-3) ** 0.8
The solution is to bind the unary minus to the three using parenthesis:
>>> (-3) ** 0.8
(-1.94829469666534+1.4155189542146727j)
>>>
The ** operator has the highest precedence over all other operators. Hence when you use
print(-3**0.8)
python first evaluates the exponential and then negates it.
But when you run
a = -3
b = 0.8
print(a**b)
a has implicitly been negated first. Hence the result is effectively a imaginary number (a negative number raised to a fractional exponent)
To solve your issue, you could do something like
print (int(a/abs(a))*(abs(a)**b))

Calculation error with pow operator

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.

Boolean operators vs Bitwise operators

I am confused as to when I should use Boolean vs bitwise operators
and vs &
or vs |
Could someone enlighten me as to when do i use each and when will using one over the other affect my results?
Here are a couple of guidelines:
Boolean operators are usually used on boolean values but bitwise operators are usually used on integer values.
Boolean operators are short-circuiting but bitwise operators are not short-circuiting.
The short-circuiting behaviour is useful in expressions like this:
if x is not None and x.foo == 42:
# ...
This would not work correctly with the bitwise & operator because both sides would always be evaluated, giving AttributeError: 'NoneType' object has no attribute 'foo'. When you use the boolean andoperator the second expression is not evaluated when the first is False. Similarly or does not evaluate the second argument if the first is True.
Here's a further difference, which had me puzzled for a while just now: because & (and other bitwise operators) have a higher precedence than and (and other boolean operators) the following expressions evaluate to different values:
0 < 1 & 0 < 2
versus
0 < 1 and 0 < 2
To wit, the first yields False as it is equivalent to 0 < (1 & 0) < 2, hence 0 < 0 < 2, hence 0 < 0 and 0 < 2.
In theory, and and or come straight from boolean logic (and therefore operate on two booleans to produce a boolean), while & and | apply the boolean and/or to the individual bits of integers. There are a lot lot of questions here on how the latter work exactly.
Here are practical differences that potentially affect your results:
and and or short-circuiting, e.g. True or sys.exit(1) will not exit, because for a certain value of the first operand (True or ..., False and ...), the second one wouldn't change the result so does not need to be evaluated. But | and & don't short-circuit - True | sys.exit(1) throws you outta the REPL.
& and | are regular operators and can be overloaded, while and and or are forged into the language (although the special method for coercion to boolean may have side effects).
This also applies to some other languages with operator overloading
and and or return the value of an operand instead of True or False. This doesn't change the meaning of boolean expressions in conditions - 1 or True is 1, but 1 is true, too. But it was once used to emulate a conditional operator (cond ? true_val : false_val in C syntax, true_val if cond else false_val in Python). For & and |, the result type depends on how the operands overload the respective special methods (True & False is False, 99 & 7 is 3, for sets it's unions/intersection...).
This also applies to some other languages like Ruby, Perl and Javascript
But even when e.g. a_boolean & another_boolean would work identically, the right solution is using and - simply because and and or are associated with boolean expression and condition while & and | stand for bit twiddling.
If you are trying to do element-wise boolean operations in numpy, the answer is somewhat different. You can use & and | for element-wise boolean operations, but and and or will return value error.
To be on the safe side, you can use the numpy logic functions.
np.array([True, False, True]) | np.array([True, False, False])
# array([ True, False, True], dtype=bool)
np.array([True, False, True]) or np.array([True, False, False])
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
np.logical_or(np.array([True, False, True]), np.array([True, False, False]))
# array([ True, False, True], dtype=bool)
The hint is in the name:
Boolean operators are for performing logical operations (truth testing common in programming and formal logic)
Bitwise operators are for "bit-twiddling" (low level manipulation of bits in byte and numeric data types)
While it is possible and indeed sometimes desirable (typically for efficiency reasons) to perform logical operations with bitwise operators, you should generally avoid them for such purposes to prevent subtle bugs and unwanted side effects.
If you need to manipulate bits, then the bitwise operators are purpose built. The fun book: Hackers Delight contains some cool and genuinely useful examples of what can be achieved with bit-twiddling.
The general rule is to use the appropriate operator for the existing operands. Use boolean (logical) operators with boolean operands, and bitwise operators with (wider) integral operands (note: False is equivalent to 0, and True to 1). The only "tricky" scenario is applying boolean operators to non boolean operands. Let's take a simple example, as described in [SO]: Python - Differences between 'and' and '&': 5 & 7 vs. 5 and 7.
For the bitwise and (&), things are pretty straightforward:
5 = 0b101
7 = 0b111
-----------------
5 & 7 = 0b101 = 5
For the logical and, here's what [Python.Docs]: Boolean operations states (emphasis is mine):
(Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument.
Example:
>>> 5 and 7
7
>>> 7 and 5
5
Of course, the same applies for | vs. or.
Boolean operation are logical operations.
Bitwise operations are operations on binary bits.
Bitwise operations:
>>> k = 1
>>> z = 3
>>> k & z
1
>>> k | z
3
The operations:
AND &: 1 if both bits are 1, otherwise 0
OR |: 1 if either bit is 1, otherwise 0
XOR ^: 1 if the bits are different, 0 if they're the same
NOT ~': Flip each bit
Some of the uses of bitwise operations:
Setting and Clearing Bits
Boolean operations:
>>> k = True
>>> z = False
>>> k & z # and
False
>>> k | z # or
True
>>>
Boolean 'and' vs. Bitwise '&':
Pseudo-code/Python helped me understand the difference between these:
def boolAnd(A, B):
# boolean 'and' returns either A or B
if A == False:
return A
else:
return B
def bitwiseAnd(A , B):
# binary representation (e.g. 9 is '1001', 1 is '0001', etc.)
binA = binary(A)
binB = binary(B)
# perform boolean 'and' on each pair of binaries in (A, B)
# then return the result:
# equivalent to: return ''.join([x*y for (x,y) in zip(binA, binB)])
# assuming binA and binB are the same length
result = []
for i in range(len(binA)):
compar = boolAnd(binA[i], binB[i])
result.append(compar)
# we want to return a string of 1s and 0s, not a list
return ''.join(result)
Logical Operations
are usually used for conditional statements. For example:
if a==2 and b>10:
# Do something ...
It means if both conditions (a==2 and b>10) are true at the same time then the conditional statement body can be executed.
Bitwise Operations
are used for data manipulation and extraction. For example, if you want to extract the four LSB (Least Significant Bits) of an integer, you can do this:
p & 0xF

Why does 1+++2 = 3?

How does Python evaluate the expression 1+++2?
How many ever + I put in between, it is printing 3 as the answer. Please can anyone explain this behavior
And for 1--2 it is printing 3 and for 1---2 it is printing -1
Your expression is the same as:
1+(+(+2))
Any numeric expression can be preceded by - to make it negative, or + to do nothing (the option is present for symmetry). With negative signs:
1-(-(2)) = 1-(-2)
= 1+2
= 3
and
1-(-(-2)) = 1-(2)
= -1
I see you clarified your question to say that you come from a C background. In Python, there are no increment operators like ++ and -- in C, which was probably the source of your confusion. To increment or decrement a variable i or j in Python use this style:
i += 1
j -= 1
The extra +'s are not incrementors (like ++a or a++ in c++). They are just showing that the number is positive.
There is no such ++ operator. There is a unary + operator and a unary - operator though. The unary + operator has no effect on its argument. The unary - operator negates its operator or mulitplies it by -1.
+1
-> 1
++1
-> 1
This is the same as +(+(1))
1+++2
-> 3
Because it's the same as 1 + (+(+(2))
Likewise you can do --1 to mean - (-1) which is +1.
--1
-> 1
For completeness there is no * unary opeartor. So *1 is an error. But there is a **
operator which is power of, it takes 2 arguments.
2**3
-> 8
1+(+(+2)) = 3
1 - (-2) = 3
1 - (-(-2)) = -1
Trying Unary Plus and Unary minus:
The unary - (minus) operator yields the negation of its numeric argument.
The unary + (plus) operator yields its numeric argument unchanged.
>>> +2
2
>>> ++2
2
>>> +++2
2
>>> -2
-2
>>> --2
2
>>> ---2
-2
>>> 1+(++2)
3
I believe it's being parsed as, the first + as a binary operation (add), and the rest as unary operations (make positive).
1 + (+(+2))
Think it as 1 + (+1*(+1*2))). The first + is operator and following plus signs are sign of second operand (= 2).
Just like 1---2 is same as 1 - -(-(2)) or 1- (-1*(-1*(2))

Categories