Is it possible to calculate n complex roots of a given number using Python? I've shortly checked it, and it looks like Python gives me wrong/incomplete answers:
(-27.0j)**(1.0/3.0) produces (2.598076211353316-1.4999999999999998j)
but proper roots should be 3 complex numbers, because every non-zero number has n different complex number nth roots. Is it possible in Python?
I don't think standard Python will do this unless you write a function for it, but you can do it with Numpy:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.roots.html
There are many multi-valued complex functions - functions that can have more than one value corresponding to any point in their domain. For example: roots, logarithms, inverse trigonometric functions...
The reason these functions can have multiple values is usually because they are the inverse of a function that has multiple values in the domain map to the same value.
When doing calculations with such functions, it would be impractical to always return all possible values. For the inverse trigonometric functions, there are infinitely many possible values.
Usually the different function values can be expressed as a function of an integer parameter k. For example, the values of log z with z = r*(cos t + i*sin t is log r + i*(t + k*2*pi) with k any integer. For the nth root, it is r**(1/n)*exp(i*(t+k*2*pi)/n with k=0..n-1 inclusive.
Because returning all possible values is impractical, mathematical functions in Python and almost all other common programming languages return what's called the 'principal value' of the function. (reference) The principal value is usually the function value with k=0. Whatever choice is made, it should be stated clearly in the documentation.
So to get all the complex roots of a complex number, you just evaluate the function for all relevant values of k:
def roots(z, n):
nthRootOfr = abs(z)**(1.0/n)
t = phase(z)
return map(lambda k: nthRootOfr*exp((t+2*k*pi)*1j/n), range(n))
(You'll need to import the cmath module to make this work.) This gives:
>>> roots(-27j,3)
[(2.59808-1.5j), (1.83691e-16+3j), (-2.59808-1.5j)]
If you want to get all roots on clean python you can create simple function to do this:
import math
def root(num, r):
base = num ** (1.0/r)
roots = [base]
for i in range(1, r):
roots.append(complex(base * math.cos(2*math.pi * i / r), base * math.sin(2*math.pi * i / r)))
return roots
Related
I had some trouble adding complex numbers in polar form in sympy.
The following code
from sympy import I, exp, pi, re, im
a = exp(2*pi/3*I)
b = exp(-2*pi/3*I)
c = a+b
print(c)
print(c.simplify())
print(c.as_real_imag())
print(re(c)+im(c)*I)
print(int(c))
print(complex(c))
gives
exp(-2*I*pi/3) + exp(2*I*pi/3)
-(-1)**(1/3) + (-1)**(2/3)
(-1, 0)
-1
-1
(-1+6.776263578034403e-21j)
What I want, is to get the simplest answer to a+b, which is -1. I can obtain this, by manually rebuilding c=a+b with re(c)+im(c)*I. Why is this necessary? And is there a better way to do this?
Simply printing c retains the polar forms, obfuscating the answer, c.simplify() leaves the polar form, but is not really helpful, and c.as_real_imag() returns a tuple. int(c) does the job, but requires the knowledge, that c is real (otherwise it throws an error) and integer (otherwise, this is not the answer I want). complex(c) kind of works, but I don't want to leave symbolic calculation. Note, that float(c) does not work, since complex(c) has a non-zero imaginary part.
https://stackoverflow.com/users/9450991/oscar-benjamin has given you the solution. If you are in polar coordinates, your expression may have exponential functions. If you don't want these you have to rewrite into trigonometric functions where special values are known for many values. For example, consider a's 2*pi/3 angle:
>>> cos(2*pi/3)
-1/2
>>> sin(2*pi/3)
sqrt(3)/2
When you rewrite a in terms of cos (or sin) it becomes the sum of those two values (with I on the sin value):
>>> a.rewrite(cos)
-1/2 + sqrt(3)*I/2
When you rewrite a more complex expression, you will get the whole expression rewritten in that way and any terms that cancel/combine will do so (or might need some simplification):
>>> c.rewrite(cos)
-1
In python when doing something like x=(-10)**(1/3) i get a complex number. I instead want to only see the one real x value which in this case would be approx -2.15. Now I do understand that I could import a math library like mpmath and generate all solutions (3 in the case), loop through them and find the one thats real. Im looking for a more elegant solution as I want to be able to create a program thats able to take in any sort of function and plug numbers into it.
here's a bit of code demonstrating what im trying to do
f= lambda x:x**(1/3)
print(f(-10))
in this case i get a complex number representing one of the 3 possible roots, but i only want the real root
The real cube root of a negative number is the negative value of the positive number's cube root:
>>> def cube_root(x):
... return -pow(-x,1/3) if x < 0 else pow(x,1/3)
...
>>> cube_root(10)
2.154434690031884
>>> cube_root(-10)
-2.154434690031884
I think this should be enough :)
def f(x):
if x < 0: return -pow(-x, 1/3)
return pow(x, 1/3)
I checked the numpy library and found the following definition for the standard deviation in numpy:
std = sqrt(mean(abs(x - x.mean())**2))
Why is the abs() function used? - Because mathematically the square of a number will be positive per definition.
So I thought:
abs(x - x.mean())**2 == (x - x.mean())**2
The square of a real number is always positive, but this is not true for complex numbers.
A very simple example: j**2=-1
A more complex (pun intended) example: (3-2j)**2=(5-12j)
From documentation:
Note that, for complex numbers, std takes the absolute value before squaring, so that the result is always real and nonnegative.
Note:
Python uses j for the imaginary unit, while mathematicians uses i.
When I run my python 3 program:
exp = 211
p = 199
q = 337
d = (exp ** (-1)) % ((p - 1)*(q - 1))
results in 211^(-1).
But when I run the calculation in wolfram alpha I get the result I was expecting.
I did some test outputs and the variables exp, p and q in the program are all the integer values I used in wolfram alpha.
My goal is to derive a private key from a (weakly) encrypted integer.
If I test my wolfram alpha result, I can decrypt the encrypted message correctly.
Wolfram Alpha is computing the modular inverse. That is, it's finding the integer x such that
exp*x == 1 mod (p - 1)*(q - 1)
This is not the same as the modulo operator %. Here, Python is simply calculating the remainder when 1/exp is divided by (p - 1)*(q - 1) when given the expression in your question.
Copying the Python code from this answer, you can compute the desired value with Python too:
>>> modinv(exp, (p - 1)*(q - 1))
45403
Wolfram Alpha does not have well-defined syntax. It takes arbitrary text you provide and attempts to figure out what you meant by that input. In this case, it decided you were probably looking for a modular inverse, and it gave you one.
Python has well-defined syntax. In Python, the parser does not take the ** and the % together and guess that that combination makes the two operators have a meaning other than their usual meaning. The ** is computed the usual way, and then % is the modulo operator. If you want a modular inverse, you'll have to write one yourself.
I think the idea here is that wolfram alpha and python define the modulo operation differently depending on the fact that you are dealing with integers or real numbers.
In this case, Wolfram Alpha is using the modulo inverse because it detects the first number is 0 < x < 1
More information about the definition on real numbers here
Python evaluates immediately (211^(-1) gets computed as 0.004739... and not ekpt as 1/211) and the modular Euclidan remainder for x and y is conventinally defined as x-floor(x/y)*y if any of x,y is a rational number. If you do your calculation with some dedicated number theoretic program like e.g.: GP/Pari
ep = 211;p = 199;q = 337;(ep ^ (-1)) % ((p - 1)*(q - 1))
you will get the result you expected to get because a) it keeps fractions as fractions as long as possible and b) knows about modular arithmetic.
Is you like Python you may take a look at the programms an libraries offered at SciPy. SymPy might be what you are looking for.
I wrote a simple Python code to solve a certain Hydraulic formula (The Manning's equation):
import math
def mannings(units,A,P,S,n):
if units=='SI':
k=1.0
elif units=='US':
k=1.49
R=A/P
V=(k/n)*(math.pow(R,(2/3)))*(math.sqrt(S))
Q=A*V
return R,V,Q
In the code above, the velocity V is calculated from the k, n, R and S. The velocity is then used to calculate the discharge Q by multiplying with Area A. The user inputs the unit convention, the A, P, S and n. k is decided on the basis of unit convention.
When I run the function using mannings('US',1.0618,2.7916,0.02,0.015), I get (0.38035535176959456, 14.047854719572745, 14.916012141242343). The R value matches the R calculated in a spreadsheet, but the V and Q are way off. The actual V should be 7.374638178
and the Q should be 7.830634155.
It'd be great if someone can tell me what's going wrong here. This is a pretty straightforward formula and I was guessing it should work easily.
Your problem is that 2/3 is an integer division and therefore evaluates to 0. You want 2.0/3 to force a floating-point division. Or else include from __future__ import division at the top of your file to use the Python 3-style division in Python 2.x.
Assuming you don't use the __future__ solution, you will also want to write your R = A / P as e.g. R = float(A) / P because otherwise, if A and P are both integers, R will also be an integer.