I am having some trouble writing this equation in Python and having it produce correct results:
y = 2.95710^-7 * x^4 – 2.34310^-5 * x^3 – 1.67*10^-4 * x^2 + 0.04938 * x – 1.083.
I have tried the following code:
y = 0.0000002957*x**4 - 0.00002343*x**3 - 0.000167*x**2 + 0.04938*x - 1.083
and also:
y = (2.957*10**-7)*x**4 - (2.343*10**-5)x**3 - (1.67*10**4)*x**2 + 0.04938*x - 1.083
any advice would be helpful, I think the problem might be the scientific notation or the exponents and the way I am inputting them
EDIT
in response to questions, the equation spits out an incorrect number than what I get on a calculator
What you have can easily be converted to Python in a very direct way. The equivalent Python statement (after fixing a flaw in the original equation...see below) is :
y = 2.95710e-7 * x**4 - 2.34310e-5 * x**3 - 1.67e-4 * x**2 + 0.04938 * x - 1.083
This involves only the simple substitution of the ^ characters, where you replace that character with e in the exponential floating point constants and with ** for raising x to an integer power.
For reference to be able to more easily compare the source with the result, here's the original equation with the one slight fix mentioned below:
y = 2.95710^-7 * x^4 – 2.34310^-5 * x^3 – 1.67^-4 * x^2 + 0.04938 * x – 1.083
UPDATE: Thanks to Pranav for pointing out a flaw in the source equation. The term 1.67*10^-4 should be changed to 1.67^-4 to match the other similar terms, and the equivalent fix made to the resulting Python equation. Those fixes were made and commented on above.
I always like to see what I'm working with in situations like this. I used matplotlib to plot this function, using an unchanged version (except for the function and the bounds on x) of this sample code. Here's what I got for x values between -500 and 500:
Thanks for answering everybody. The most helpful answer was using "e" instead of scientific notation (*10^x).
Related
subs (from sympy library in Python) does not replace a subexpression in all cases except simple ones. MATLAB copes with this task perfectly. Is it possible to somehow achieve the same result as in MATLAB?
Sympy
MATLAB
This fails because the product 2*(x + y) automatically expands to the sum of 2x + 2*y, as #hpaulj points out. And #oscarbenjamin points out that re-arranging your substitution so it targets only an atomic part of the expression you desire to replace will work.
In addition, if you backsubstitute to restore the original atom you will see if the substitution was not able to be fully done while retaining the original variables:
>>> f = (x + y)**2 + 1/(4*x + 4*y + sin(2*x + 2*y))
>>> (f+x).subs(x,z-y).subs(y,z-x)
x + z**2 + 1/(4*z + sin(2*z))
Looking at the Sympy documentation, there seems to be an "expand" function which can be called upon to expand polynomial expressions; however, in practice, this is not working for me. I started off using imaginary numbers:
import sympy
sympy.expand((x - 1)(x + i)(x - i))
Hoping for "x^3 - x^2 + x - 1", however, instead, this returned the following error: module 'sympy' has no attribute 'expand'
I then changed the expression I wanted to be expanded, as this had caused me to assume that Sympy could not handle complex numbers, to what can be seen below:
import sympy
sympy.expand((x - 1)(x - 1)(x + 1))
Yet this returned the same error.
The imaginary i is represented by the capital I in sympy. To have a multiplication, an * needs to be used explicitly. Also, in Python ^ is strictly reserved for a boolean (or bitwise) exclusive or. Power is represented as **.
from sympy import symbols, I, expand
x = symbols('x')
print(expand((x - 1)*(x + I)*(x - I)))
Output: x**3 - x**2 + x - 1
Note that an alternative way to call expand() is as expression.expand() (or ((x - 1)*(x + I)*(x - I)).expand() as in the example). Often this is a handy way to concatenate several operations.
I don't have problem to run
import sympy
x = sympy.Symbol('x')
i = sympy.Symbol('i')
sympy.expand( (x - 1)*(x + i)*(x - i) )
and this gives me
-i**2*x + i**2 + x**3 - x**2
The only idea: you created file with name sympy.py and now import sympy loads your file instead of module sympy and it can't find expand in your file. You have to rename your file sympy.py to something different (which is not name of other module).
But you didn't add full error message in question so I can't confirm it.
I'm currently trying to calculate a negative group delay of analog filters by using symbolic calculations in Python. The problem that I'm currently trying to resolve is to get rid of some very small imaginary coefficients.
For example, consider fraction with such numerator (imaginary parts are bolded):
(-1.705768*w^18 + 14.702976409432*w^16 + 1.06581410364015e-14*I*w^15 - 28.7694094371724*w^14 - 9.94759830064144e-14*I*w^13 + 59.0191623753299*w^12 + 5.6843418860808e-14*I*w^11 + 24.7015297857594*w^10 - 1.13686837721616e-13*I*w^9 - 549.093511217598*w^8 - 5.6843418860808e-14*I*w^7 + 1345.40434657845*w^6 + 2.27373675443232e-13*I*w^5 - 1594.14046181284*w^4 - 1.13686837721616e-13*I*w^3 + 980.58940367608*w^2 - 254.8428594382)
Is there any way to automatically round those small coefficients, so they would be equal 0 (in general any negligligible values)? Or at least, can I somehow filter imaginary values out? I've tried to use re(given_fraction), but it couldn't return anything. Also standard rounding function can't cope with symbolic expressions.
The rounding part was already addressed in Printing the output rounded to 3 decimals in SymPy so I won't repeat my answer there, focusing instead of dropping imaginary parts of coefficients.
Method 1
You can simply do re(expr) where expr is your expression. But for this to work, w must be known to be a real variable; otherwise there is no way for SymPy to tell what the real part of (3+4*I)*w is. (SymPy symbols are assumed to be complex unless stated otherwise.) This will do the job:
w = symbols('w', real=True)
expr = # your formula
expr = re(expr)
Method 2
If for some reason you can't do the above... another, somewhat intrusive, way to drop the imaginary part of everything is to replace I with 0:
expr = expr.xreplace({I: 0})
This assumes the expression is already in the expanded form (as shown), so there is no (3+4*I)**2, for example; otherwise the result would be wrong.
Method 3
A more robust approach than 2, but specialized to polynomials:
expr = Poly([re(c) for c in Poly(expr, w).all_coeffs()], w).as_expr()
Here the expression is first turned into a polynomial in w (which is possible in your example, since it has a polynomial form). Then the real part of each coefficient is taken, and a polynomial is rebuilt from them. The final part as_expr() returns it back to expression form, if desired.
Either way, the output for your expression:
-1.705768*w**18 + 14.702976409432*w**16 - 28.7694094371724*w**14 + 59.0191623753299*w**12 + 24.7015297857594*w**10 - 549.093511217598*w**8 + 1345.40434657845*w**6 - 1594.14046181284*w**4 + 980.58940367608*w**2 - 254.8428594382
def nu(r):
'''Returns the stellar density function.'''
return 1 / ( r * (1 + (r / a))**3)
mass_int = lambda r: 4 * r**2 * nu(r)
print(mass_int(0))
This gives me a divide by zero error, presumably because of the 1/r term being evaluated in isolation. Is using sympy to form the correct algebraic expression the only way around this? Seems absurd.
It's not doing anything wrong. Given r = 0:
1 / ( r * (1 + (r / a))**3)
= 1 / ( 0 * (1 + (0 / a))**3)
= 1 / ( 0 * (1 + 0 )**3)
= 1 / ( 0 * 1 **3)
= 1 / ( 0 * 1 )
= 1 / 0
So when you ask for nu(0) you get an error. It doesn't look ahead and do special algebra things, it just throws the error. Python is not magic, it's not absurd that you'd need sympy for this.
I suggest you just add a special case to mass_int for r == 0.
This isn't a python question, or even a computer programming question. It's simple math.
f(x) = 1 / (x * (1 + x/a)**3)
g(x) = 4x**2
h(x) = 4x / (1 + x/a)**3
Is there a difference between f(g(r)) and h(r)? Of course there is. Even though the plots look exactly the same, f(g(0)) is undefined, and on a plot must show as a point discontinuity.
As an intelligent user of this function, you can recognize that the point discontinuity is there. If you choose, you can replace f(g(r)) with h(r). The only difference will be the desired one of having the function defined at 0.
Math doesn't do that on its own, and no programming language will reduce the function composition for you on its own, unless you ask it to, because you are the user, and you're supposed to know what you want from a program. If you create a function composition that has a point discontinuity, it's expected that you did so for a reason. The intelligence is expected to be in the programmer, not in the compiler. Either compose and reduce the function by yourself, or do something like having sympy do it. Either way, it's up to you to make it explicit to the computer that these two functions should be related to each other.
I have a simple factorization problem in sympy that I cannot sort out. I've had great success with sympy working with quite complex integrals, but I'm flummoxed by something simple.
How do I get
phi**2 - 2*phi*phi_0 + phi_0**2 - 8
to factor to
(phi - phi_0)**2 - 8
?
I've already tried the factor function
factor(phi**2 - 2*phi*phi_0 + phi_0**2 - 8,phi-phi_0)
which yields the same old solution.
As I noted in the comment, such "partial factorizations" are not unique (for instance, x**2 + 5*x + 7 equals (x + 2)*(x + 3) + 1 and (x + 1)*(x + 4) + 3, and once you understand what's going on it's not hard to come up with examples of your own).
There are ways to do such things manually, but it's hard to know what to tell you because I don't know what generality you are looking for. For instance, probably the easiest way to do this particular example is
>>> print(A.subs(phi, x + phi_0).factor().subs(x, phi - phi_0))
(phi - phi_0)**2 - 8
That is, let x = phi - phi_0 (SymPy isn't smart enough to replace phi - phi_0 with x, but it is smart enough to replace phi with x - phi_0, which is the same thing). This doesn't generalize as nicely if you want to factor in terms of a larger polynomial, or if you don't know what you are aiming for. But given the names of your variables, I'm guessing phi - phi_0 is all you care about.
Beyond this, I should point out that you can more or less do any kind of simplification you want by digging in and writing your own algorithms that dig into the expressions. Take a look at http://docs.sympy.org/latest/tutorial/manipulation.html to get you started. Also take a look at all the methods of Expr. There are quite a few useful helper functions if you end up writing such a thing, such as the various as_* methods.