Init
This commit is contained in:
97
Vektorrechnung.py
Normal file
97
Vektorrechnung.py
Normal file
@@ -0,0 +1,97 @@
|
||||
import math
|
||||
import decimal
|
||||
decimal.getcontext().prec = 30
|
||||
|
||||
|
||||
class Vector(object):
|
||||
CANNOT_NORMALIZE_ZERO_VECTOR_MSG = 'Cannot normalize the zero vector'
|
||||
|
||||
def __init__(self, coordinates):
|
||||
try:
|
||||
if not coordinates:
|
||||
raise ValueError
|
||||
self.coordinates = tuple([decimal.Decimal(x) for x in coordinates])
|
||||
self.dimension = len(coordinates)
|
||||
|
||||
except ValueError:
|
||||
raise ValueError('The coordinates must be nonempty')
|
||||
|
||||
except TypeError:
|
||||
raise TypeError('The coordinates must be an iterable')
|
||||
|
||||
def __str__(self):
|
||||
return 'Vector: {}'.format(self.coordinates)
|
||||
|
||||
def __eq__(self, v):
|
||||
return self.coordinates == v.coordinates
|
||||
|
||||
# LINEAR ALGEBRA METHODS
|
||||
def plus(self, v):
|
||||
new_coordinates = [x+y for x,
|
||||
y in zip(self.coordinates, v.coordinates)]
|
||||
return Vector(new_coordinates)
|
||||
|
||||
def minus(self, v):
|
||||
new_coordinates = [x-y for x,y in zip(self.coordinates, v.coordinates)]
|
||||
return Vector(new_coordinates)
|
||||
|
||||
def times_scalar(self,c):
|
||||
new_coordinates = [c*x for x in self.coordinates]
|
||||
return Vector(new_coordinates)
|
||||
|
||||
def magnitude(self):
|
||||
coordinates_squared = [x**2 for x in self.coordinates]
|
||||
return decimal.Decimal(math.sqrt(sum(coordinates_squared)))
|
||||
|
||||
def normalized(self):
|
||||
try:
|
||||
magnitude = self.magnitude()
|
||||
return self.times_scalar(decimal.Decimal('1.0')/magnitude)
|
||||
except ZeroDivisionError:
|
||||
raise Exception(self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG)
|
||||
|
||||
def dot(self,v):
|
||||
return sum([x*y for x,y in zip(self.coordinates, v.coordinates)])
|
||||
|
||||
def angle_inner_with(self, v, in_degrees = False):
|
||||
try:
|
||||
u1 = self.normalized()
|
||||
u2 = v.normalized()
|
||||
#Capture within range of dot product to be within 1 & -1
|
||||
u1u2dot = replace_if_within_tolerance(u1.dot(u2),1)
|
||||
u1u2dot = replace_if_within_tolerance(u1.dot(u2),-1)
|
||||
angle_in_radians = math.acos(u1u2dot)
|
||||
|
||||
if in_degrees:
|
||||
return math.degrees(angle_in_radians)
|
||||
else:
|
||||
return angle_in_radians
|
||||
except Exception as e:
|
||||
if str(e) == self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG:
|
||||
raise Exception('Cannot compute an angle with the zero vector')
|
||||
else:
|
||||
raise e def is_zero(self, tolerance = 1e-10):
|
||||
#returns true if magnitude is less than tolerance
|
||||
return self.magnitude() < tolerance
|
||||
|
||||
def is_parallel_to(self, v):
|
||||
return ( self.is_zero() or
|
||||
v.is_zero() or
|
||||
self.angle_inner_with(v) == 0 or
|
||||
self.angle_inner_with(v) == math.pi )
|
||||
|
||||
def is_orthogonal_to(self, v, tolerance = 1e-10):
|
||||
return abs(self.dot(v)) < tolerance
|
||||
|
||||
def replace_if_within_tolerance(val, compared_against, tolerance = 1e-10):
|
||||
if abs(val - compared_against) < tolerance:
|
||||
return compared_against
|
||||
else:
|
||||
return val
|
||||
|
||||
#Values from Parallel Orthogonal Quiz, math domain error
|
||||
|
||||
v = Vector([’-7.579’, ‘-7.88’])
|
||||
w = Vector([‘22.737’, ‘23.64’])
|
||||
print(v.is_parallel_to(w)) print(v.is_orthogonal_to(w))
|
||||
#v = Vector([’-2.029’, ‘9.97’, ‘4.172’]) w = Vector([’-9.231’, ‘-6.639’, ‘-7.245’]) print(v.is_parallel_to(w)) print(v.is_orthogonal_to(w)) v = Vector([’-2.328’, ‘-7.284’, ‘-1.214’]) w = Vector([’-1.821’, ‘1.072’, ‘-2.94’]) print(v.is_parallel_to(w)) print(v.is_orthogonal_to(w)) v = Vector([‘2.118’, ‘4.827’]) w = Vector([‘0’, ‘0’]) print(v.is_parallel_to(w)) print(v.is_orthogonal_to(w))
|
||||
Reference in New Issue
Block a user