ValueError: negative number cannot be raised to a fractional power - python

When I tried this in terminal
>>> (-3.66/26.32)**0.2
I got the following error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: negative number cannot be raised to a fractional power
However, I am able to do this in two steps like,
>>> (-3.66/26.32)
-0.13905775075987842
>>> -0.13905775075987842 ** 0.2
-0.6739676327771593
Why this behaviour? What is the way to solve this in single line?

Raising to a power takes precedence over the unary minus sign.
So you have -(0.13905775075987842 ** 0.2) and not (-0.13905775075987842) ** 0.2 as you expect:
>>> -0.13905775075987842 ** 0.2
-0.6739676327771593
>>> (-0.13905775075987842) ** 0.2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: negative number cannot be raised to a fractional power
If you want it to work you should write (-3.66/26.32 + 0j)**0.2
>>> (-3.66/26.32 + 0j)**0.2
(0.5452512685753758+0.39614823506888347j)
Or switch Python 3 as noted by #TimPietzcker.

Switch to Python 3 which automatically promotes the result to a complex number:
>>> (-3.66/26.32)**0.2
(0.5452512685753758+0.39614823506888347j)

Related

Why lambdify never stops?

x = symbols('x')
ch = 'exp(cos(cos(exp((sin(-0.06792841536110628))**(-6.045461643745118)))))'
f = lambdify(x, ch, "numpy")
print(float(f(2)))
It does not work, the programm is running and never ends(no error is issued).
My goal is to avoid this kind of cases (among multiple cases) by doing a try/except but i can't as there is no error
Why no error is released?
How can i avoid these cases ?
Thanks for your helping me !
In general, I'm not sure you can. SymPy or NumPy will keep trying to compute the number until precision is exhausted. But you can create a function that will raise and error if numbers are out of bounds for your interest:
>>> from sympy import cos as _cos, I, exp
>>> def cos(x):
... if abs(x) > 10**20: raise ValueError
... return _cos(x)
>>> exp(cos(cos(exp(5*(1+I)))))
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 2, in cos
ValueError
>>> f = lambda x: exp(cos(cos(exp(x))))
>>> f(sin(-0.06792841536110628)**-6.045461643745118)
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 1, in <lambda>
File "<string>", line 2, in cos
ValueError
But you have to think carefully about when you want to raise such an error. For example, SymPy has no trouble computing f(100) or f(100*I) if the non-error-catching cos is used. So think about when actually you want the error to rise.
lambdify is a lexical translator, converting a sympy expression to a python/numpy function.
Make a string with a symbol:
In [27]: ch = 'exp(cos(cos(exp((sin(x))**(-6.045461643745118)))))'
sympify(ch) has no problem, because it doesn't need to do any numeric calculation. So lambdify also works:
In [28]: f=lambdify(x,ch)
In [29]: f?
Signature: f(x)
Docstring:
Created with lambdify. Signature:
func(x)
Expression:
exp(cos(cos(exp((sin(x))**(-6.045461643745118)))))
Source code:
def _lambdifygenerated(x):
return (exp(cos(cos(exp(sin(x)**(-6.045461643745118))))))
The equivalent mpmath:
def _lambdifygenerated(x):
return (exp(cos(cos(exp(sin(x)**(mpf((1, 54452677612106279, -53, 56))))))))
And a working numeric evaluation:
In [33]: f(0j)
Out[33]: mpc(real='nan', imag='0.0')

How does the `j` suffix for complex numbers work? Can I make my own suffix?

I know what are complex numbers and how they mathematically work, but how is it done for python to know it's complex just by putting a j after a digit ?
>>> j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1*j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1j
1j
>>> 1j**2
(-1+0j)
Can I make my own suffix, let's say p (for strictly positive) ?
Could I do something working like this ?
>>> ... some weird stuff here ...
>>> p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined
>>> 1*p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined
>>> -1p
1p
>>> 0p
1p
>>>
This is built into Python's grammar, just like the decimal point is, or the e in scientific notation (1e10 etc.). The j makes a numeric literal imaginary.
Python does not allow you to change this. That doesn't mean you can't--you could amend the grammar--but then the language is no longer Python.
The closest approximation allowed in Python would be by implementing an operator.
>>> class StrictlyPositive:
def __rmatmul__(self, number):
return abs(number)
>>> p = StrictlyPositive()
>>> -1#p
1
But you have to be careful of operator precedence when doing stuff like this. Why not just use the builtin abs directly?

How to dereference an object in Python?

I have a function with returns a tuple:
def gradiant(params, data):
Q1 = params[0]
Q2 = params[1]
dQ1 = sum(2*(y_i - Q1*x_i - Q2)*(x_i) for x_i, y_i in data)
dQ2 = sum(-2*(y-i - Q1*x_i - Q2) for x_i, y_i in data)
return (dQ1, dQ2)
I'm trying to print the returned values:
grad = gradiant(params, Data)
for x in grad: print(x)
Output:
<generator object <genexpr> at 0x7fdfe009adc0>
<generator object <genexpr> at 0x7fdfe009a5f0>
How do I get to print the integer values?
You have a y-i instead of y_i. It produced a NameError for me. I fixed the typo and it worked fine (I assume, anyway - it printed two numbers).
However, the more interesting issue is how errors are handled within generator expressions (as the typo was part of the generator expression you sent to sum()). I got a NameError, but you got generator expression objects. Look at this function call with an unpacked generator that should contain a TypeError:
>>> print(*(''.join(item2) for item2 in range(3)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print() argument after * must be a sequence, not generator
Now let's see what we get by printing the actual object:
>>> print(''.join(item2) for item2 in range(3))
<generator object <genexpr> at 0x00000000028945E8>
That makes some sense, as generators are lazily evaluated and it was never actually called. But let's see what happens when we send it to list(), which should force evaluation:
>>> print(list(''.join(item2) for item2 in range(3)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
TypeError: can only join an iterable
There's the expected error.
How about a valid generator that contains an invalid generator?
>>> print(*(list(''.join(item2) for item2 in range(3)) for i in range(1)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print() argument after * must be a sequence, not generator
The same uninformative error.
What if we use a list comprehension instead of a generator expression?
>>> print(*[''.join(item2) for item2 in range(3)])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
TypeError: can only join an iterable
We get the informative error we were expecting.
Unfortunately, I don't know why this happens, but be extra-careful with generator expressions.

Best way to develop a programme without using reload

I see from other discussions that reload is considered an unnecessary operation and a bad way to develop programmes. People say to use doctest and unittest. I must be missing something. To develop a programme I write it in a module, load the module into an eclipse console, experiment in the console by running little samples of code, then I spot an error in the module or decide to change something. Surely the quickest thing to do is save the module, reload it and carry on working in the console.
Is there a better way?
Basically instead of trying things out in the console, try things out by writing tests. It's almost the same amount of typing, but repeatable (you can check if things still work after you make changes) and it works as a rudimentary form of documentation.
Here's a contrived example of how you could use doctest and test driven development in comparision with testing by entering code at the console, with a recursive factorial function being used as an example:
Console:
First attempt:
def factorial(x)
pass
Console:
>>> factorial(7)
SyntaxError: invalid syntax
Second attempt:
def factorial(x):
return x*x-1
Console:
>>> factorial(7)
42
Third attempt:
def factorial(x):
return x * factorial(x-1)
Console:
>>> factorial(7)
RuntimeError: maximum recursion depth reached # StackOverflow! (basically)
Fourth attempt:
def factorial(x):
if x == 0:
return 1
else:
return x * factorial(x-1)
Console:
>>> factorial(5)
120
In the end, we get the right answer, but at each stage we have to go back to the console and write the same thing. This is alright for a short program like this, but for a program with many functions, and more complex interactions and possibilities to be tested it would take a very long time. Programming is about automating repetitive tasks, and testing is a repetitive task, so it makes sense to automate it. And in Python, tools to do just this are provided for you.
Behold - the doctest module: (example taken from the docs)
First attempt:
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
"""
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
First test (just run the program):
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
ok
Trying:
factorial(30)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be >= 0
ok
Trying:
factorial(30.1)
Expecting:
Traceqwrqaeqrback (most recent call last):
...
ValueError: n must be exact integer
**********************************************************************
File "C:/Python33/doctestex.py", line 14, in __main__.factorial
Failed example:
factorial(30.1)
Exception raised:
Traceback (most recent call last):
File "C:\Python33\lib\doctest.py", line 1287, in __run
compileflags, 1), test.globs)
File "<doctest __main__.factorial[3]>", line 1, in <module>
factorial(30.1)
File "C:/Python33/doctestex.py", line 32, in factorial
raise ValueError("n must be exact integer")
ValueError: n must be exact integer
Trying:
factorial(30.0)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
ok
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
1 of 6 in __main__.factorial
6 tests in 2 items.
5 passed and 1 failed.
***Test Failed*** 1 failures.
>>> ================================ RESTART ================================
>>>
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
**********************************************************************
File "C:/Python33/doctestex.py", line 4, in __main__.factorial
Failed example:
[factorial(n) for n in range(6)]
Expected:
[1, 1, 2, 6, 24, 120]
Got:
[None, None, None, None, None, None]
Trying:
factorial(30)
Expecting:
265252859812191058636308480000000
**********************************************************************
File "C:/Python33/doctestex.py", line 6, in __main__.factorial
Failed example:
factorial(30)
Expected:
265252859812191058636308480000000
Got nothing
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be >= 0
**********************************************************************
File "C:/Python33/doctestex.py", line 8, in __main__.factorial
Failed example:
factorial(-1)
Expected:
Traceback (most recent call last):
...
ValueError: n must be >= 0
Got nothing
Trying:
factorial(30.1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be exact integer
**********************************************************************
File "C:/Python33/doctestex.py", line 14, in __main__.factorial
Failed example:
factorial(30.1)
Expected:
Traceback (most recent call last):
...
ValueError: n must be exact integer
Got nothing
Trying:
factorial(30.0)
Expecting:
265252859812191058636308480000000
**********************************************************************
File "C:/Python33/doctestex.py", line 18, in __main__.factorial
Failed example:
factorial(30.0)
Expected:
265252859812191058636308480000000
Got nothing
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
**********************************************************************
File "C:/Python33/doctestex.py", line 22, in __main__.factorial
Failed example:
factorial(1e100)
Expected:
Traceback (most recent call last):
...
OverflowError: n too large
Got nothing
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
6 of 6 in __main__.factorial
6 tests in 2 items.
0 passed and 6 failed.
***Test Failed*** 6 failures.
Then when we finish the program (and at all stages between) we just press one button and that does all our testing for us. If you were working with a team on a bigger project, you could, for instance, write the test data to file and use the failures to see where you need to focus on.
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
ok
Trying:
factorial(30)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be >= 0
ok
Trying:
factorial(30.1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be exact integer
ok
Trying:
factorial(30.0)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
ok
1 items had no tests:
__main__
1 items passed all tests:
6 tests in __main__.factorial
6 tests in 2 items.
6 passed and 0 failed.
Test passed.
And (provided you added all the test cases to the docstring) now you can ship or integrate or whatever the program and it much fewer bugs than it would've if you just tested for the things you thought mattered each time you changed something, rather than the things you thought could possibly ever matter at the start of the development process.
Not to mention you now have the basis for your documentation! Running the program in the console, and then entering help(factorial) will now give you this:
Help on function factorial in module __main__:
factorial(n)
Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
You can then use a number of tools (pydoc is one in the standard library) to turn the docstrings into formatted HTML helpfiles.
Of course, this is only one of many testing tools you can use with Python. Others include the more powerful unittest module, and the less powerful technique of adding assert statements into your code.

How to fix this python program?

import math
def p(n):
return 393000*((288200/393000)^n * math.exp(-(288200/393000)))/math.factorial(n)
print p(3)
When I run it, I get the following error message:
Traceback (most recent call last):
File "poisson.py", line 6, in <module>
print p(3)
File "poisson.py", line 4, in p
return 393000*((288200/393000)^n * math.exp(-(288200/393000)))/math.factoria
l(n)
TypeError: unsupported operand type(s) for ^: 'int' and 'float'
Replace ^ with ** in
(288200/393000)^n
Bear in mind that
288200/393000
Returns 0
Maybe you should try using decimal numbers:
import math
def p(n):
a = 393000.0 # <-- notice the .0
b = 288200.0
c = b / a
return a * ( c**n * math.exp(-c) )/ math.factorial(n)
print p(3)
Returns:
12406.890756
Is the ^ supposed to mean exponentiation? If so, use ** instead.
You can also use math.pow:
>>> import math
>>> math.pow(3,2)
9.0
Though actually it looks like maybe this isn't the best idea, since math.pow is more for C extension compatibility, and doesn't handle all the cases that ** does:
>>> 2**3000
1230231922161117176931558813276752514640713895736833715766118029160058800614672948775360067838593459582429649254051804908512884180898236823585082482065348331234959350355845017413023320111360666922624728239756880416434478315693675013413090757208690376793296658810662941824493488451726505303712916005346747908623702673480919353936813105736620402352744776903840477883651100322409301983488363802930540482487909763484098253940728685132044408863734754271212592471778643949486688511721051561970432780747454823776808464180697103083861812184348565522740195796682622205511845512080552010310050255801589349645928001133745474220715013683413907542779063759833876101354235184245096670042160720629411581502371248008430447184842098610320580417992206662247328722122088513643683907670360209162653670641130936997002170500675501374723998766005827579300723253474890612250135171889174899079911291512399773872178519018229989376L
vs.
>>> import math
>>> math.pow(2, 3000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: math range error
see http://mail.python.org/pipermail/python-list/2003-November/236169.html for a little more detail
EDIT: In response to your question as to why it returns 0.0, that's because you are raising 0 to a power - you are using / for division, which by default is integer division and will truncate. use from __future__ import division to get floating point divison.

Categories