# The 'math' library provides many mathematical constants
# and functions for working with real numbers. Before using
# these, we must import the library.
#
# For example, the square-root function is 'sqrt(...)'.
# Because it belongs to the 'math' library, we call it by
# writing the library name, followed by a dot ('.'), followed
# by the function name:
#
# math.sqrt(...)
#
# In Python, multiplication must always be written explicitly
# using '*'. Thus, 'a*b' is the product of 'a' and 'b', while
# 'ab' is simply a variable name.
import math
# Mathematically, these expressions are equal:
#
# (5 + 2*sqrt(7))(5 - 2*sqrt(7))
# = 5^2 - (2*sqrt(7))^2
# = 25 - 28
# = -3.
#
# Numerically, however, the first result may differ slightly
# from -3 because sqrt(7) cannot be represented exactly as a
# floating-point number.
#
# Notice that Python uses '**' for exponentiation, not '^'.
print( (5 + 2*math.sqrt(7))*(5 - 2*math.sqrt(7)) )
print( 5*5 - 2*2*7 )
print( 5**2 - 2**2*7 )
print( "\nRoots of a polynomial with real roots:" )
# Find the roots of the polynomial
#
# 2
# 3.8x + 4.2x - 1.7.
#
# For
#
# 2
# ax + bx + c = 0,
#
# the quadratic formula gives
#
# 2
# -b +/- sqrt(b - 4ac)
# x = ---------------------.
# 2a
############################################
# Assign the variables 'a', 'b', and 'c' the
# three values shown below.
#
# Do not read
#
# a = 3.8
#
# as "'a' equals 3.8." The '=' symbol is the
# assignment operator, so read this as
#
# "'a' is assigned the value 3.8."
#
# After the assignment has been performed,
# 'a' does equal 3.8. To test whether two
# values are equal, however, Python uses the
# equality operator '=='.
############################################
a = 3.8
b = 4.2
c = -1.7
# Be sure to put parentheses around the denominator.
# For example,
#
# (-b - math.sqrt(b**2 - 4*a*c))/2*a
#
# is interpreted as
#
# ((-b - math.sqrt(b**2 - 4*a*c))/2)*a,
#
# which is not the quadratic formula.
print( (-b - math.sqrt(b**2 - 4*a*c))/(2*a) )
print( (-b + math.sqrt(b**2 - 4*a*c))/(2*a) )
print( "\nArithmetic with the imaginary unit:" )
# Python represents the imaginary unit using '1j'.
# The character 'j' by itself is simply a variable name.
#
# Thus, write '1j' for the imaginary unit. For clarity,
# parentheses can be used when raising it to a power.
print( (1j)**5 )
print( (5 + 2j)*(5 - 2j) )
print( 5*5 - 2*2*(1j)*(1j) )
print( 5**2 - (2j)**2 )
print( "\nRoots of a polynomial with complex roots:" )
# The 'math' library works with real numbers. Consequently,
# math.sqrt(...) cannot calculate the square root of a
# negative real number. For example,
#
# math.sqrt(-1)
#
# results in
#
# ValueError: math domain error
#
# The 'cmath' library provides corresponding mathematical
# functions for complex numbers.
import cmath
# Now find the roots of the polynomial
#
# 2
# 3.8x + 4.2x + 1.7.
#
# Here the discriminant is negative, so the two roots
# are a complex-conjugate pair.
c = 1.7
print( (-b - cmath.sqrt(b**2 - 4*a*c))/(2*a) )
print( (-b + cmath.sqrt(b**2 - 4*a*c))/(2*a) )
############# IMPORTANT #############
# In Python, the imaginary unit must have a
# numeric coefficient:
#
# 1j
#
# You cannot write simply 'j' unless you have
# previously assigned a value to the variable
# named 'j'.
#
# More generally, Python recognizes expressions
# such as
#
# 2j
# 3.5j
# -4j
#
# as imaginary numbers.
############# IMPORTANT #############
############# IMPORTANT #############
# The 'math' library operates on real numbers.
# Thus,
#
# math.sqrt(-1)
#
# raises a ValueError rather than returning a
# complex number.
#
# If a calculation may require the square root
# of a negative number, use the 'cmath' library:
#
# cmath.sqrt(-1)
#
# which returns
#
# 1j
############# IMPORTANT #############