Calculation error with pow operator - python

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.

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))

Ambiguity in basic arithmetic operations Python [duplicate]

This question already has answers here:
ValueError: negative number cannot be raised to a fractional power
(2 answers)
Closed 5 years ago.
Here is the scenario:
In [5]: (2.0 - 5.0**(0.5)) ** (1.0/3.0)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-5-d064023f1ac5> in <module>()
----> 1 (2.0 - 5.0**(0.5)) ** (1.0/3.0)
ValueError: negative number cannot be raised to a fractional power
In [7]: -1.0 ** (1.0/3.0)
Out[7]: -1.0
The above operation is being done on a python interpreter. For the first expression, it is giving value error and says that negative number can't have fractional power !! So, firstly, why is this error as obviously, -ve numbers can have cube root or fifth root etc. Also, if that is the case, it should be consistent while in second case, it gives no error when -1 is raised to fractional power (1/3).
Can someone explain why is this the case?
The ** operator has specific binding behaviour; from the power operator 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.
So your second example is executed as:
-(1.0 ** (1.0/3.0))
That is to say, the - unary operator applies to the result of ** as that operator binds more tightly. As a result you have positive number is raised to the power 1/3rd, and only then made negative.
In your first example, the expression is parsed as
(2.0 - (5.0**(0.5))) ** (1.0/3.0)
There is no unary operator here, but the ** power operator does have a higher precedence than the binary - subtraction operator.
This then resolves as
(2.0 - 2.23606797749979) ** (1.0/3.0)
which is
(-0.2360679774997898) ** (1.0/3.0)
so is trying to raise a negative number to a fraction.
Python 2 ** (and the pow() function) don't support producing a complex number support when the inputs are at most float objects. Convert your negative float value to a complex() number first:
>>> (-1.0) ** 0.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: negative number cannot be raised to a fractional power
>>> (-1+0j) ** 0.5
(6.123233995736766e-17+1j)
>>> (2+0j - 5.0**(0.5)) ** (1.0/3.0)
(0.30901699437494756+0.535233134659635j)
This changed in Python 3, where a complex result is returned for a negative number raised to a fractional power.

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

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).

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