Objective Learn about Python's Decimal module. Learn about Decimal objects. Review examples of code containing Decimal objects. Learn how to use Decimal objects to perform calculations on complex numbers. Become familiar with numbers containing many thousands of decimal digits. Create a new class CompleX. Use class CompleX and Python's Decimal module to solve the cubic equation.

Lesson

Calculations using Python's Decimal module can be performed with (almost) any precision selectable by the user. Unfortunately many functions which you might expect to find in the module don't exist, for example, trigonometric functions and functions that manipulate complex numbers. For these functions you have to find them elsewhere or write them for yourself.

Here are some examples that highlight the power of Python's Decimal Module.

Making the Decimal object

The following function verifies that we are working with Decimal objects. It provides for a tuple containing two decimal objects to simulate a complex number.

from decimal import *

getcontext().prec += 5  # Extra digits for intermediate steps.

D = Decimal

def makeDecimal (x) :
'''
x is a single object convertible to Decimal object/s.
returns Decimal object or
tuple containing 2 Decimal objects to simulate complex or
exits with error status
'''

if isinstance(x, Decimal) :
return (x)
if isinstance(x, int) or isinstance(x, float) :
return (Decimal(str(x)))
if isinstance(x, complex) :
return ( Decimal(str(x.real)), Decimal(str(x.imag)) )
if isinstance(x, str) :
status = 0
try : x1 = Decimal(x)
except : status = -1
if not status : return x1

status = 0
try : x1 = eval(x)
except : status = -1
if status :
print ('makeDecimal: bad status after eval.')
exit(79)

if isinstance(x1, str) :
print ('makeDecimal: eval must not produce another string.')
exit(78)
return makeDecimal(x1)
print ('makeDecimal: input must be Decimal, int, float, complex or str.')
exit(77)

Trigonometric Functions

The following trigonometric functions are sufficient to convert from complex type polar to complex type rectangular and vice-versa.

For the functions $\cos x$ and $\sin x$ see Recipes.

arctan $x$ We'll try $\arctan x$ first because it's easily understood and implemented, and it can be used to calculate $\pi$ because the result of this expression (as in all theoretical math) is in radians.

$\arctan x=\sum _{n=0}^{\infty }{\frac {(-1)^{n}}{2n+1}}x^{2n+1}=x-{\frac {x^{3}}{3}}+{\frac {x^{5}}{5}}-\cdots {\text{for }}|x|\leq 1,\ x\neq \pm i$ def arctan (tanθ) : # The Python interpreter recognizes international text. Handy.
# value returned is in radians.
# Check input:
x = makeDecimal (tanθ)
if not isinstance(x, Decimal) :
print ('arctan: type of input should be Decimal.')
exit(79)

if not x : return 0 # tan(0) = 0

if abs(x) > 1 :
# abs() function is valid for Decimal objects.
print ('arctan: abs(x) should be <= 1.')
exit(78)
if x < 0 :
print ('arctan: input must be >= 0.')
exit(77) # Only non-negative values in this implementation.

sum = x
x_sq = x*x

divisor = 3

last_dividend = x

multiplier = -1

getcontext().prec += 2  # extra digits for intermediate steps

almostZero = Decimal('1e-' + str(getcontext().prec))

while 1 :
this_dividend = last_dividend * x_sq
if this_dividend < almostZero : break
sum += multiplier * this_dividend / divisor

last_dividend = this_dividend
multiplier *= -1
divisor += 2

getcontext().prec -= 2  # Restore original precision.
return sum+0 # Apply original precision to sum.

Calculating $\pi$ There are many ways to calculate $\pi$ . For example:

$\pi =6*\arctan(\tan 30)=6*\arctan({\frac {\sqrt {3}}{3}}).$ Based on the following, we will perform six calculations of $\pi$ and compare the results.

$\pi =30*\arctan(\tan 6)$ $\pi =24*\arctan(\tan 7.5)$ $\pi =12*\arctan(\tan 15)$ $\pi =8*\arctan(\tan 22.5)$ $\pi =6*\arctan(\tan 30)$ $\pi =5*\arctan(\tan 36)$ precision = getcontext().prec
getcontext().prec = 502

tan6 = (
( (D('10') - D('20').sqrt()).sqrt() + D('3').sqrt() - D('15').sqrt() )
/
2
)
tan7_5 = D(6).sqrt() - D(3).sqrt() + D(2).sqrt() - 2
tan15 = D(2) - D(3).sqrt()
tan22_5 = D(2).sqrt() - 1
tan30 = D('3').sqrt()/3
tan36 = ( D(5) - 2*(D(5).sqrt()) ).sqrt()

values = [
(tan6, 30),
(tan7_5, 24),
(tan15, 12),
(tan22_5, 8),
(tan30, 6),
(tan36, 5)
]

L2 = [ (v*arctan(v)).quantize(
D('1e-'+str(getcontext().prec-3)), rounding=ROUND_HALF_UP
)
for v in values
]

print ('number of calculations =', len(L2))

set2 = set(L2)
len(set2) == 1 or exit(93) # All values in L2 must be equal.
π, = list(set2)
str_π = str(π)

L3 = [
str_π[start:start+70]
for start in range(0,len(str_π),70)
]

str1 = '"' + '" + \n"'.join(L3) + '"'

print (
'''
π = (
{} )
len(str(π)) = {}
isinstance(π, Decimal): {}
'''.format ( str1,
len(str_π),
isinstance(π, Decimal)
)
)

getcontext().prec = precision
number of calculations = 6

π = (
"3.14159265358979323846264338327950288419716939937510582097494459230781" +
"6406286208998628034825342117067982148086513282306647093844609550582231" +
"7253594081284811174502841027019385211055596446229489549303819644288109" +
"7566593344612847564823378678316527120190914564856692346034861045432664" +
"8213393607260249141273724587006606315588174881520920962829254091715364" +
"3678925903600113305305488204665213841469519415116094330572703657595919" +
"5309218611738193261179310511854807446237996274956735188575272489122793" +
"81830119491" )
len(str(π)) = 501
isinstance(π, Decimal): True

All six calculations agree to 500 digits of precision and π is available globally as a Decimal object.

tan $(\theta /2)$ $\tan {\frac {\theta }{2}}$ $=\csc \theta -\cot \theta$ .

def tanθ_2 (tanθ):
'''
tan(θ/2) = csc θ - cot θ
x = tanθ
'''
x = makeDecimal(tanθ)
if not isinstance(x, Decimal) :
print ('tanθ_2: x should be Decimal.')
exit(76)

if x == 0 : return 0

if x < 0 :
# Only non-negative values in this implementation.
print ('tanθ_2: input < 0.')
exit(75)

getcontext().prec += 2  # extra digits for intermediate steps
cscθ = ((Decimal(1)+x*x).sqrt()) / x
cotθ = Decimal(1)/x
tan_θ2 = cscθ - cotθ
getcontext().prec -=2

return (tan_θ2 + 0)

decATAN2 $(y,x)$ For the corresponding function using floating point arithmetic see math.atan2(y, x)

This function invokes $arctan(x)\ 0\leq x\leq 1$ .

If $\tan \theta >1,\ x={\frac {1}{\tan \theta }}$ and the result is ${\frac {\pi }{2}}-\arctan(x).$ However this function invokes $\arctan(x)$ with a value less than $0.325$ so that the expression $x^{2n+1}$ in the expansion of $\arctan x$ vanishes as rapidly as possible. Therefore:

$75=90-\arctan({\frac {1}{\tan 75}})$ $68=4\arctan(\tan {\frac {68}{4}})$ $32=2\arctan(\tan {\frac {32}{2}})$ $12=\arctan(\tan 12)$ def decATAN2 (y,x) :
'''
y
Input is value -.
x
Both x,y must be convertible to Decimal object.
Only 1 of x or y may be 0.
Returns value of angle in degrees.
Value of π must be available globally.
'''
x = makeDecimal(x)
if not isinstance(x, Decimal) :
print ('decATAN2: type of x',type(x),'should be Decimal.')
exit(70)

y = makeDecimal(y)
if not isinstance(y, Decimal) :
print ('decATAN2: type of y',type(y),'should be Decimal.')
exit(69)

if x == y == 0 :
print ('decATAN2: both x and y cannot be 0.')
exit(68)

if y == 0 :
if x > 0 : return 0
return 180

if x == 0 :
if y > 0 : return 90
return 270

if abs(x) == abs(y) :
if x > 0 :
if y > 0 : return 45
return 360-45
if y > 0 : return 180-45
return 180+45

getcontext().prec += 2  # Extra digits for intermediate steps.
tanθ = abs(y)/abs(x)

flip = 0
if tanθ > Decimal('3.078') : # > 72 degrees
tanθ = 1/tanθ
flip += 1

reductionCount = 0
while tanθ > Decimal('0.325') : # > 18 degrees
tanθ = tanθ_2 (tanθ)
reductionCount += 1

θ = arctan(tanθ)
if flip :
θ = π/2 - θ
else :
while reductionCount :
θ *= 2
reductionCount -= 1

θinDegrees = θ*180/π
if x > 0 :
if y < 0 :
θinDegrees = 360-θinDegrees
else :
if y > 0 :
θinDegrees = 180-θinDegrees
else :
θinDegrees = 180+θinDegrees

getcontext().prec -= 2
return θinDegrees+0

def degreesToRadians (θinDegrees) :
'''
Value of π must be available globally.
Value returned: -π < radians <= π
-180 degrees is returned as π.
270 degrees is returned as -π/2
'''
x = makeDecimal(θinDegrees)

if not isinstance(x, Decimal) :
print ('degreesToRadians: type of x should be Decimal.')
exit(54)

x = x % 360
if x < 0 : x += 360
if x > 180 : x -= 360
return x * π/180

Complex Functions

Within the context of this page a complex number is contained in a tuple with three members, thus:

(modulus, phaseInDegrees, 'polar')

The above tuple represents complex number $modulus\ *\ (\ \cos(phaseInDegrees)\ +\ 1j*\sin(phaseInDegrees)\ )$ .

Or:

(realPart, imaginaryPart, 'rect')

where $realPart,imaginaryPart$ are the rectangular coordinates of complex number $realPart\ +\ 1j*imaginaryPart$ .

The four values $modulus,phaseInDegrees,realPart,imaginaryPart$ are all Decimal objects.

The rectangular format is useful for addition and subtraction of complex numbers.

The polar format is useful for raising a complex number to a power including a power less than unity.

Both formats are useful for multiplication, division and square root.

When working with polar format it's generally more advantageous to work with a positive modulus. Therefore:

$-n*(\cos \phi +1j*\sin \phi )=n*(\cos(\phi \pm 180)+1j*\sin(\phi \pm 180))$ and, for example:

${\sqrt {-4}}={\sqrt {-4(\cos 0+1j*\sin 0)}}={\sqrt {4(\cos 180+1j*\sin 180)}}=2(\cos 90+1j*\sin 90)=2*1j*1=2j$ and the other sqrt of $-4$ is:

${\sqrt {4(\cos(-180)+1j*\sin(-180))}}=2(\cos(-90)+1j*\sin(-90))=2*1j*(-1)=-2j$ .

>>> (2j)**2 ; (-2j)**2
(-4+0j)
(-4+0j)
>>>

Both of the following complex tuples equate to 0:

>>> (0,0,'rect')
>>> (0,anyNumber,'polar')

The following functions will enable us to do some serious math with complex numbers, such as solving the cubic equation with three real roots.

checkComplex(x)

This function verifies that the object is a valid complex tuple.

def checkComplex(x) :
if not isinstance(x,tuple) :
print ('checkComplex: input type should be tuple')
exit(69)
if not (len(x) == 3) :
print ('checkComplex:', 'len(x) =', len(x), 'should be 3 in', x)
exit(68)
if not isinstance(x, Decimal) :
print ('checkComplex:', 'x =', x, 'should be Decimal in', x)
exit(67)
if not isinstance(x, Decimal) :
print ('checkComplex:', 'x =', x, 'should be Decimal in', x)
exit(66)
if not isinstance (x, str) :
print ('checkComplex: x must be str.')
exit(65)
if (x not in ('polar', 'rect')) :
print ('checkComplex:', 'x =', x, 'should be "polar"/"rect" in', x)
exit(64)

makeComplex(x)

def makeComplex(x) :
'''
Input can be tuple with 1,2 or 3 members.
If 1 or 2 members, 'rect' is understood.
The one member or single object may be int, float, complex, CompleX
or string convertible to int, float or complex.

x = makeComplex(4)
x = makeComplex((4,))
x = makeComplex(('4',0))
x = makeComplex((4,'0', 'rect'))
x = makeComplex(4+0j)
x = makeComplex('4+0j')
x = makeComplex(('4+0j',))
In all seven cases above x = ( Decimal('4'), Decimal('0'), 'rect' )

output is always
(modulus, phase, "polar") or
(real_part, imag_part, "rect")
modulus, phase, real_part, imag_part are Decimal objects.
'''
if isinstance(x, CompleX) :  # New class CompleX (note the spelling.)
x.check()
return (x.r, x.i, 'rect')

if isinstance(x, tuple) :
if len(x) not in (1,2,3) :
print ('makeComplex: input has wrong length.',len(x),'should be 3.')
exit(76)
if len(x) == 3 :
if not isinstance (x, str) :
print ('makeComplex: x must be str.')
exit(75)
if x not in ('polar','rect') :
print ('makeComplex: type of complex in x not recognized.')
exit(75)
v1,v2,type_ = makeComplex(x[:2])
output = (v1,v2,x)
checkComplex(output)
return output

if len(x) == 2 :
v1,v2 = [ makeDecimal (v) for v in x ]
if not isinstance(v1, Decimal) :
print ('makeComplex: v1 should be Decimal.')
exit(74)
if not isinstance(v2, Decimal) :
print ('makeComplex: v2 should be Decimal.')
exit(73)
output = (v1,v2, 'rect')
return output

x = x
t1 = makeDecimal (x)
if isinstance(t1,Decimal) :
output = (t1,Decimal(0),'rect')
return output

if (isinstance(t1, tuple) and len(t1) == 2) :
output = t1 + ('rect',)
checkComplex(output)
return output

print ('makeComplex: t1 must be tuple with length 2.')
exit(72)

convertComplex(x)

def convertComplex(x) :
'''
If input is rectangular, output is polar and vice-versa
'''
x = makeComplex(x)

if x == 'polar' :
modulus, phase = x, x
a,b = (modulus*cosθ, modulus*sinθ)
output = (a,b,'rect')
else :
real,imag = x, x
modulus = (real*real + imag*imag).sqrt()
phase = decATAN2(imag, real)
output = (modulus, phase, 'polar')

output = makeComplex(output)
return output

clean_complex (x)

def clean_complex (x) :
'''
output = clean_complex (x)
output is input returned as complex tuple
with values "cleaned".
1e-50 is returned as 0.
12.999999999999999..........9999999999999999999999
is returned as 13.
12.888888888888........8888888888888888888888888888 is left unchanged.
Note the following Decimal operations:
>>> getcontext().prec = 20
>>> Decimal('3.9999999999999999999999999999999')
Decimal('3.9999999999999999999999999999999')
>>> Decimal('3.9999999999999999999999999999999')+0
Decimal('4.0000000000000000000')
>>> (Decimal('3.9999999999999999999999999999999')+0).normalize()
Decimal('4')
>>>
>>> Decimal(76500)
Decimal('76500')
>>> Decimal(76500).normalize()
Decimal('7.65E+4')
>>> Decimal(76500).normalize()+0
Decimal('76500')
>>>
Hence the line: ((value+0).normalize()+0)
'''
x = makeComplex(x)
getcontext().prec -= 3

almostZero = Decimal ('1e-' + str(getcontext().prec) )
L1 = [
( ( (v, Decimal(0))[int(offset)] + 0 ).normalize() + 0 )
for v in x[:2]
for offset in (
(v > -almostZero) and (v < almostZero),
)
]

for offset in range (0,2,1) :
v1 = L1[offset]
if v1 == 0 : pass
else :
t1 = v1.as_tuple()
if len( t1 ) < getcontext().prec  : pass
else : L1[offset] = x[offset]

getcontext().prec += 3

while x == 'polar' :
if L1 == 0 :
L1 = L1 ; break
if L1 < 0 :
L1 = (L1).copy_negate()
L1 += 180
L1 %= 360
if L1 <= -180 : L1 += 360
if L1 > 180 : L1 -= 360
break

return tuple(L1)

CompleX_to_complex (x)

def CompleX_to_complex (x) :
'''
complex, float = CompleX_to_complex (x)
'''
x = makeComplex(x)
if x == 'polar' : x = convertComplex (x)

x = clean_complex (x)

cx1 = complex( float(x), float(x) )
fl1 = float(cx1.real)
if cx1.imag : fl1 = None
return (cx1, fl1)

Arithmetic functions

'''
Calculation is rectangular.
The spelling of SuM indicates type CompleX.
'''
ToP, BottoM = [ CompleX(v) for v in (v1,v2) ]

sum = (ToP.r+BottoM.r, ToP.i+BottoM.i, 'rect')

SuM = CompleX(sum)

return SuM

subtractComplex(v1,v2)

def subtractComplex(v1,v2) :
'''
DifferencE = subtractComplex(v1,v2)
where DifferencE = v1 - v2
Calculation is rectangular.
'''

ToP, BottoM = [ CompleX(v) for v in (v1,v2) ]
difference = (ToP.r-BottoM.r, ToP.i-BottoM.i, 'rect')
DifferencE = CompleX(difference)

return DifferencE

multiplyComplex (v1, v2)

def multiplyComplex (v1, v2) :
'''
ProducT = multiplyComplex (multiplicand, multiplier)
Calculation is 'rect'.
'''

ToP, BottoM = [ CompleX(v) for v in (v1,v2) ]
a,b = ToP.r, ToP.i
c,d = BottoM.r, BottoM.i
product = ( a*c-b*d, b*c+a*d, 'rect' )
ProducT = CompleX(product)
return ProducT

divideComplex (dividend, divisor)

def divideComplex (dividend, divisor) :
'''
QuotienT = divideComplex (dividend, divisor)
Calculation is 'polar'.
divisor must be non-zero.
if dividend == 0, output is 0.
'''
DividenD, DivisoR = [ CompleX(v) for v in (dividend, divisor) ]
if not DivisoR.m :
print ('divideComplex: polar divisor must be non-zero.')
exit(88)
if (not DividenD.m) : return CompleX(0)
quotient = (DividenD.m/DivisoR.m, DividenD.p-DivisoR.p, 'polar')
return CompleX(quotient)

Exponential functions

complexSQRT (x)

def complexSQRT (x) :
'''
RooT = complexSQRT (x)
calculation is 'polar'.
'''
CX1 = CompleX(x)
if not CX1.m : return CompleX(0)

modulus, phase = CX1.m, CX1.p
if modulus < 0 :
modulus *= -1 ; phase += 180
modulus = modulus.sqrt()
phase = phase/2
root = (modulus,phase,'polar')
return CompleX(root)

complexCUBEroot (x)

def complexCUBEroot (x) :
'''
RooT = complexCUBEroot (x)
'polar' output is useful because the other 2 cube roots are:
(root, root+120, 'polar')
(root, root+240, 'polar')
'''
CX1 = CompleX(x)
if not CX1.m : return CompleX(0)

# Calculating the cube root is a polar operation.

modulus, phase = CX1.m, CX1.p
if modulus < 0 :
modulus *= -1 ; phase += 180
modulus_of_root = modulus ** ( Decimal(1) / Decimal(3) )
phase_of_root = phase/3
root = (modulus_of_root, phase_of_root, 'polar')
RooT = CompleX(root)

return RooT

class CompleX

class CompleX :
'''
This class has 5 attributes:
self.r : the real coordinate of the complex number
self.i : the imaginary coordinate of the complex number
self.m : the modulus of the complex number
self.p : the phase of the complex number in degrees
self.c : the class expressed as Python type complex
'''

def __init__(self, value=0):
self.set(value)
return

def check(self) :
#        print ('entering check(self) :')
precisions = [] ; status = 0
for v in (self.r, self.i, self.m, self.p) :
if not isinstance(v, Decimal) :
print ('value not Decimal:', str(v)[:20]) ; status = -1 ; continue
precisions += [len(v.as_tuple())]
if not isinstance(self.c, complex) :
print ('self.c not complex:', str(self.c)[:20]) ; status = -1

if status : exit(39)

cx1, not_used = CompleX_to_complex ((self.r, self.i, 'rect'))
if cx1 != self.c : print ("""
for self = {}
Rect values don't match self.c:
{}
{}""".format(
self,cx1,self.c
)
)
cx1, not_used = CompleX_to_complex ((self.m, self.p, 'polar'))
if cx1 != self.c : print ("""
for self = {}
Polar values don't match self.c:
{}
{}""".format(
self,cx1,self.c
)
)
return

def set(self, value=Decimal(0)):
#        print ('entering set(self, ',value,'):')

t1 = makeComplex(value)
if t1 == 'rect' :
self.r, self.i = t1[:2]
if not self.r and not self.i : self.m = self.p = Decimal(0)
else :
t1 = convertComplex(value)
self.m, self.p = t1[:2]
else :
self.m, self.p = t1[:2]
if not self.m : self.r = self.i = self.p = Decimal(0)
else :
t1 = convertComplex(value)
self.r, self.i = t1[:2]

self.c, not_used = CompleX_to_complex ((self.r, self.i, 'rect'))
self.check()
return

def clean(self) :
#        print ('entering clean(self) :')
self.check()
#output = clean_complex (x)
self.r, self.i = clean_complex ((self.r, self.i, 'rect'))
self.m, self.p = clean_complex ((self.m, self.p, 'polar'))
self.check()
return

def _print(self) :
'''
output a string containing all the info
about self and suitable for printing.'''
self.check()
return '''
self = {}
real = {}
imag = {}
modulus = {}
phase = {}
as type complex: {}
'''.format(
self,
self.r,    self.i,
self.m,    self.p,
self.c,
)

The above code highlights the power of Python in a new class called CompleX. When a new instance of this class is created, it can be accessed through its attributes and changed through its methods with the simplest of syntax.

Seemingly complicated functions such as complex cube root can be implemented in only a few lines of simple code.

Examples

CX1 = CompleX()
print ('isinstance(CX1, CompleX):', isinstance(CX1, CompleX))
print ('CX1 =', CX1._print())
isinstance(CX1, CompleX): True
CX1 =
self = <__main__.CompleX object at 0x101a463c8>
real = 0
imag = 0
modulus = 0
phase = 0
as type complex: 0j
CX2 = CompleX((5,30,'polar'))
print ('isinstance(CX2, CompleX):', isinstance(CX2, CompleX))
print ('CX2 =', CX2._print())
isinstance(CX2, CompleX): True
CX2 =
self = <__main__.CompleX object at 0x101245240>
real = 4.33012701892219323381861585376468
imag = 2.50000000000000000000000000000000
modulus = 5
phase = 30
as type complex: (4.330127018922194+2.5j)
CX3 = CompleX('-5+12j')
print ('isinstance(CX3, CompleX):', isinstance(CX3, CompleX))
print ('CX3 =', CX3._print())
isinstance(CX3, CompleX): True
CX3 =
self = <__main__.CompleX object at 0x101416f28>
real = -5.0
imag = 12.0
modulus = 13.0
phase = 112.619864948040426172949010876680
as type complex: (-5+12j)
CX2 = CX1 # shallow copy.
CX2 = CompleX(CX1) # deep copy.
CX3.check() # This should not produce error.
CX3.set(-7.5)
print ('CX3 =', CX3._print())
self = <__main__.CompleX object at 0x101415f60>
real = -7.5
imag = 0
modulus = 7.5
phase = 180
as type complex: (-7.5+0j)

Solving the cubic equation Figure 1: Cubic function and X intercepts.

Origin at point $(0,0)$ .
Intercepts at points $(3,0),\ (-1,0),\ (-2.5,0)$ The cubic equation is expressed thus: $ax^{3}+bx^{2}+cx+d=0$ where both $a,d$ are non-zero.

We will solve the equation $2x^{3}+x^{2}-16x-15=0$ as an example of the use of Python's Decimal module and the new class CompleX. See Figure 1.

a,b,c,d = (2,1,-16,-15)

A = 2*b*b*b - 9*a*b*c + 27*a*a*d
C = b*b-3*a*c

p = -3*C
q = -A

The depressed cubic and Vieta's substitution

Let $x={\frac {-(b+t)}{3a}}$ , substitute this value of $x$ in the cubic equation and produce the depressed cubic $t^{3}+pt+q=0.$ Let $t=w-{\frac {p}{3w}}$ , substitute this value of $t$ in the depressed equation and produce the quadratic: $W^{2}+qW+C^{3}=0$ where $W=w^{3}$ .

Therefore, $W={\frac {-q\pm {\sqrt {q^{2}-4C^{3}}}}{2}}$ .

disc = q*q - 4*C*C*C

RooT = complexSQRT (disc)

DividenD = addComplex ( -q, RooT )

W = divideComplex(DividenD, 2)

isinstance(W, CompleX) or exit(48)

r = Decimal(3).sqrt()

W.clean()

print ('\n################\nW =', W._print())
################
W =
self = <__main__.CompleX object at 0x10137cbe0>
real = -665
imag = 685.892119797275408236868751236328
modulus = 955.33920677422215800938250724701
phase = 134.113967095785813976410473653471
as type complex: (-665+685.8921197972754j)

The cube roots Figure 2: Three cube roots of W.
$w_{1}$ = RooT1; $w_{2}$ = RooT2; $w_{3}$ = RooT3.
$W\ =\ w_{1}^{3}\ =\ w_{2}^{3}\ =\ w_{3}^{3}$ .
Phase of $W\ =\ \alpha$ Phase of $w_{1}\ =\ \beta \ =\ {\frac {\alpha }{3}}$ Phase of $w_{2}\ =\ \beta \ +\ 120.$ Phase of $w_{3}\ =\ \beta \ -\ 120.$ RooT1 =  complexCUBEroot(W)
t1 = (RooT1.m, RooT1.p+120, 'polar')
t2 = (RooT1.m, RooT1.p-120, 'polar')
RooT2 = CompleX(t1)
RooT3 = CompleX(t2)
for root in ( RooT1, RooT2, RooT3 ) :
root.clean()
print ('++++++++++++++++\nRooTx:', root._print())

print ('''
self.i
------- = {}
sqrt(3)
'''.format(
float(root.i/r)
)
)
# Each value of w has format (k + 1j*m*sqrt(3)). It can be shown that t = 2k.
t = 2*root.c.real
x = -(b+t)/(3*a)
result = a*x*x*x + b*x*x + c*x + d
print ('x =', x, 'result =',result)
++++++++++++++++
RooTx:
self = <__main__.CompleX object at 0x1012572e8>
real = 7
imag = 6.92820323027550917410978536602346
modulus = 9.84885780179610472174621141491761
phase = 44.7046556985952713254701578844903
as type complex: (7+6.928203230275509j)

self.i
------- = 4.0
sqrt(3)

x = -2.5 result = 0.0
++++++++++++++++
RooTx:
self = <__main__.CompleX object at 0x101257240>
real = -9.5
imag = 2.59807621135331594029116951225890
modulus = 9.84885780179610472174621141491761
phase = 164.704655698595271325470157884490
as type complex: (-9.5+2.598076211353316j)

self.i
------- = 1.5
sqrt(3)

x = 3.0 result = 0.0
++++++++++++++++
RooTx:
self = <__main__.CompleX object at 0x10136d400>
real = 2.5
imag = -9.52627944162882511440095487828231
modulus = 9.84885780179610472174621141491761
phase = -75.2953443014047286745298421155097
as type complex: (2.5-9.526279441628825j)

self.i
------- = -5.5
sqrt(3)

x = -1.0 result = 0.0

The three roots of the given cubic are $-1,3,-2.5$ .

Assignments Calculate the value of $\pi$ to 10,000 places of decimals. When calculating $\pi$ : >>> Decimal(str(math.pi)) Decimal('3.141592653589793') # π accurate to precision 16. >>> >>> Decimal(math.pi) Decimal('3.141592653589793115997963468544185161590576171875') # Not an accurate value of π. Why? >>> # 3.14159265358979323846264338327950288419716939937510582097494459230781 # Correct value of π. $N$ = $(9,60,$ 'polar'$)$ . What are the square roots of $N$ ? $({\sqrt {9}},\ {\frac {60}{2}},$ 'polar'$)\ =\ (\pm 3,\ 30,$ 'polar'$)$ . $(-3,\ 30,$ 'polar'$)$ = $(3,\ 30\pm 180,$ 'polar'$)$ $r_{1}=(2,60,$ 'polar'$)$ is one of the cube roots of a certain number $N$ . What is the number $N$ ? What are the other two cube roots of $N$ ? $r_{1}=2(\cos 60+1j*\sin 60).$ $N=r_{1}^{3}=2^{3}(\cos(60*3)+1j*\sin(60*3))=8(\cos 180+1j*\sin 180)=8(-1)=-8$ . The other two cube roots of $N$ are: $r_{2},r_{3}=(2,60\pm 120,$ 'polar'$)$ Given that CX1 is type CompleX, add method sqrt() to class CompleX so that the expression CX1.sqrt() returns the square root of CX1 as type CompleX.