# coding=utf-8 import math class Vector(object): """docstring for Vector""" """根据坐标轴列表输入 创建向量, 并创建该向量所处的空间维度""" def __init__(self, coordinates): super(Vector, self).__init__() try: if not coordinates: raise ValueError self.coordinates = tuple(coordinates) self.dimension = len(coordinates) except ValueError: raise ValueError('The coordinates must be nonempty') except TypeError: raise TypeError('The coordinates must be an iterable') # '''能够使python的内置print函数 输出向量坐标轴''' def __str__(self): return 'Vector: {}'.format(self.coordinates) # 点积 def dot(self, v): new_cordinates = [x*y for x,y in zip(self.coordinates,v.coordinates)] return sum(new_cordinates) # 弧度 def radian(self,v): vectorDot = self.dot(v) result = vectorDot / (self.magnitude()*v.magnitude()) return math.acos(result) # 角度 def angle(self,v): vectorRadian = self.radian(v) result = 180 / math.pi * vectorRadian return result v1 = Vector([7.887, 4.138]) v2 = Vector([-8.802, 6.776]) print(v1.dot(v2)) v3 = Vector([-5.955, -4.904, -1.874]) v4 = Vector([-4.496, -8.755, 7.103]) print(v3.dot(v4)) v5 = Vector([3.183, -7.627]) v6 = Vector([-2.668, 5.319]) print(v5.radian(v6)) v7 = Vector([7.35,0.221,5.188]) v8 = Vector([2.751,8.259,3.985]) print(v7.angle(v8)) # 输出结果 # -41.382286 # 56.397178 # 3.07202630984 # 60.2758112052 # [Finished in 0.1s]
优化后
# coding=utf-8 from math import sqrt, acos, pi from decimal import Decimal, getcontext class Vector(object): """docstring for Vector""" """根据坐标轴列表输入 创建向量, 并创建该向量所处的空间维度""" CANNOT_NORMALIZE_ZERO_VECTOR_MSG = 'Cannot normalize the zero vector' def __init__(self, coordinates): super(Vector, self).__init__() try: if not coordinates: raise ValueError self.coordinates = tuple([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') # '''能够使python的内置print函数 输出向量坐标轴''' def __str__(self): return 'Vector: {}'.format(self.coordinates) # 计算向量长度 def magnitude(self): coordinates_squared = [x**2 for x in self.coordinates] return sqrt(sum(coordinates_squared)) # 将向量归一化 def normalized(self): try: magnitude = self.magnitude() return Vector([Decimal(x) *(Decimal(1.0)/ Decimal(magnitude)) for x in self.coordinates]) except ZeroDivisionError: raise Exception('Cannot normalized the zero myVector2') # 点积 def dot(self, v): return sum([x*y for x,y in zip(self.coordinates, v.coordinates)]) # 角度弧度 def angle_with(self,v,in_degress=False): try: u1 = self.normalized() u2 = v.normalized() angle_in_radians = acos(u1.dot(u2)) if in_degress: degrees_per_radian = 180./pi return angle_in_radians * degrees_per_radian 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 # 为什么要处理这些小数, 如果两个向量指向同一方向,它们的点积则是二者大小的点积 # 但是有时候,因为计算精度丢失 使比例不对, 这样就会在acos函数中产生范围错误 v1 = Vector([7.887, 4.138]) v2 = Vector([-8.802, 6.776]) print(v1.dot(v2)) v3 = Vector([-5.955, -4.904, -1.874]) v4 = Vector([-4.496, -8.755, 7.103]) print(v3.dot(v4)) v5 = Vector([3.183, -7.627]) v6 = Vector([-2.668, 5.319]) print(v5.angle_with(v6, in_degress = False)) v7 = Vector([7.35,0.221,5.188]) v8 = Vector([2.751,8.259,3.985]) print(v7.angle_with(v8,in_degress = True)) # 输出结果 -41.38228599999999454398391663 56.39717800000000569975711073 3.07202630984 60.2758112052 [Finished in 0.2s]