这是 Udacity 线性代数进修课程中的一个作业,我已经以我的方式解决了它,尽管这个作业有一个解决方案,但我正在尝试以我的方式解决它。 但是我在查找 2 个矢量(即矢量 v1 和 v2 之间的角度(时出现错误。
该程序有 2 个问题问 2 解决。但即使有相同的。但是对程序是给不同的输出,即使有"角度"功能是相同的。
import math
from decimal import Decimal,getcontext
getcontext().prec = 30
class Vector(object):
def __init__(self,coordinates):
try:
if not coordinates:
raise ValueError
#if coordinates is not passed then it will rise Value Error
self.coordinates = tuple([Decimal(x)for x in coordinates])
#Outside Class :-Vector.coordinates will give print vectors in tuple form
#Inside Class :- self.coordinates will print vectors in tuple form
self.dimension = len(coordinates)
#Outside Class :-Vector.dimension will print vectors dimension/size
#Inside Class :- self.dimension will print vectors dimension/size
except ValueError:
raise ValueError('The coordinates must be non empty')
except TypeError:
raise TypeError('The coordinates must be itterable')
def __str__(self):
return 'Vector:{}'.format(self,coordinates)
def __eq__(self,v):
return self.coordinates == v.coordinates
def add (self,v):
coordinates=[]
for i in range(0,self.dimension):
i=self.coordinates[i]+v.coordinates[i]
coordinates.append(i)
return coordinates
def mul(self,v):
coordinates=[]
for i in range(0,self.dimension):
i=self.coordinates[i]*v.coordinates[i]
coordinates.append(i)
return coordinates
def sub (self,v):
coordinates=[]
for i in range(0,self.dimension):
i=self.coordinates[i]-v.coordinates[i]
coordinates.append(i)
return coordinates
def scal_mul(self,s):
coordinates=[]
for i in self.coordinates:
i=i*Decimal(s)
coordinates.append(i)
return coordinates
def magnitude(self):
mag = 0
for i in self.coordinates:
i=i*i
mag =mag+i
return math.sqrt(mag)
def magnitude1(self):
mag = 0
coordinate_squre=[i*i for i in self.coordinates]
return math.sqrt(sum(coordinate_squre))
# def normalize(self):
# try:
# recip = Decimal(1)/self.magnitude()
# return Vector(self.scal_mul(recip))
# except ZeroDivisionError:
# raise Exception("Can not Normalize Zero Vector")
def normalize(self):
try:
recip = 1/self.magnitude()
return self.scal_mul(recip)
except ZeroDivisionError:
raise Exception("Can not Normalize Zero Vector")
def dot_product(self,v):
mul = self.mul(v)
return sum(mul)
def dot_product2(self,v):
self.mul = [x*y for x,y in zip(self.coordinates,v.coordinates)]
return sum(self.mul)
#-----------------angle functionn is giving wrong answer-------------
def angle_rad(self,v):
norm = self.normalize()
angle = 1/ math.cos(norm.dot_product2(v))
return angle
def angle(self,v,in_degree=False):
nrm_self = self.normalize()
nrm_v = v.normalize()
angle_rad = math.acos(nrm_self.dot_product2(nrm_v))
if in_degree:
angle_in_degree = angle_rad * 180./math.pi
return angle_in_degree
else:
return angle_rad
v1 = Vector([7.887,4.138])
v2 = Vector([-8.802,6.776])
print(v1.angle(v2))
v1 = Vector([-7.579,-7.88])
v2 = Vector([22.737,23.64])
v2.angle(v1)
此代码给出错误如下
AttributeError Traceback (most recent call last)
<ipython-input-44-2087e4f0ca26> in <module>()
101 v1 = Vector([7.887,4.138])
102 v2 = Vector([-8.802,6.776])
--> 103 print(v1.angle(v2))
104 v1 = Vector([-7.579,-7.88])
105 v2 = Vector([22.737,23.64])
<ipython-input-44-2087e4f0ca26> in angle(self, v, in_degree)
92 nrm_self = self.normalize()
93 nrm_v = v.normalize()
---> 94 angle_rad = math.acos(nrm_self.dot_product2(nrm_v))
95 if in_degree:
96 angle_in_degree = angle_rad * 180./math.pi
AttributeError: 'list' object has no attribute 'dot_product2'
另一个具有完全相同角度功能的程序是
import math
class Vector(object):
def __init__(self,coordinates):
try:
if not coordinates:
raise ValueError
#if coordinates is not passed then it will rise Value Error
self.coordinates = tuple(coordinates)
#Outside Class :-Vector.coordinates will give print vectors in tuple form
#Inside Class :- self.coordinates will print vectors in tuple form
self.dimension = len(coordinates)
#Outside Class :-Vector.dimension will print vectors dimension/size
#Inside Class :- self.dimension will print vectors dimension/size
except ValueError:
raise ValueError('The coordinates must be non empty')
except TypeError:
raise TypeError('The coordinates must be itterable')
def __str__(self):
return 'Vector:{}'.format(self,coordinates)
def __eq__(self,v):
return self.coordinates == v.coordinates
def add (self,v):
coordinates=[]
for i in range(0,self.dimension):
i=self.coordinates[i]+v.coordinates[i]
coordinates.append(i)
return coordinates
def mul(self,v):
coordinates=[]
for i in range(0,self.dimension):
i=self.coordinates[i]*v.coordinates[i]
coordinates.append(i)
return coordinates
def sub (self,v):
coordinates=[]
for i in range(0,self.dimension):
i=self.coordinates[i]-v.coordinates[i]
coordinates.append(i)
return coordinates
def scal_mul(self,s):
coordinates=[]
for i in self.coordinates:
i=i*s
coordinates.append(i)
return coordinates
def magnitude(self):
mag = 0
for i in self.coordinates:
i=i*i
mag =mag+i
return math.sqrt(mag)
def magnitude1(self):
mag = 0
coordinate_squre=[i*i for i in self.coordinates]
return math.sqrt(sum(coordinate_squre))
def normalize(self):
try:
recip = 1/self.magnitude()
return Vector(self.scal_mul(recip))
except ZeroDivisionError:
raise Exception("Can not Normalize Zero Vector")
def dot_product(self,v):
mul = self.mul(v)
return sum(mul)
def dot_product2(self,v):
self.mul = [x*y for x,y in zip(self.coordinates,v.coordinates)]
return sum(self.mul)
#-----------------angle functionn is giving wrong answer-------------
def angle_rad(self,v):
norm = self.normalize()
angle = 1/ math.cos(norm.dot_product2(v))
return angle
def angle(self,v,in_degree=False):
nrm_self = self.normalize()
nrm_v = v.normalize()
angle_rad = math.acos(nrm_self.dot_product2(nrm_v))
if in_degree:
angle_in_degree = angle_rad * 180./math.pi
return angle_in_degree
else:
return angle_rad
v1 = Vector([7.887,4.138])
v2 = Vector([-8.802,6.776])
print(v1.angle(v2))
v1 = Vector([-7.579,-7.88])
v2 = Vector([22.737,23.64])
v2.angle(v1)
它给出的错误如下
2.0023426999774925
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-214-2e3bee12967a> in <module>()
95 v1 = Vector([-7.579,-7.88])
96 v2 = Vector([22.737,23.64])
---> 97 v2.angle(v1)
98
<ipython-input-214-2e3bee12967a> in angle(self, v, in_degree)
82 nrm_self = self.normalize()
83 nrm_v = v.normalize()
---> 84 angle_rad = math.acos(nrm_self.dot_product2(nrm_v))
85 if in_degree:
86 angle_in_degree = angle_rad * 180./math.pi
ValueError: math domain error
我们可以看到它们具有相同的角度功能
第一个程序的问题在于 normalize 方法返回坐标列表,return self.scal_mul(recip)
但不会将该列表转换为 Vector 对象,如第二个程序,而是return Vector(self.scal_mul(recip))
.调用nrm_self.dot_product2(nrm_v)
时,对象nrm_self是一个列表,而不是一个 Vector,并且它没有 dot_product2 方法。您需要像在第二个程序中一样添加对构造函数 Vector(( 的显式调用,以便能够从 norm_self 对象调用方法。
抛出数学域错误是因为dot_product2返回大于 1 的值(不幸的是,1.000000000000002(,并且反余弦 acos(x( 仅针对 -1 和 1 之间的值定义。这是由于归一化中的数值误差,可以通过始终将倒数稍微向上舍入来纠正。