commit 7baabd7b0f67fbaade8ab6bbe0d33000c92645a5 Author: Sven Riwoldt Date: Mon Nov 25 10:04:18 2024 +0000 Init diff --git a/Vektorrechnung.py b/Vektorrechnung.py new file mode 100644 index 0000000..66a92d5 --- /dev/null +++ b/Vektorrechnung.py @@ -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))