为什么一个函数在Python中给出了不同的错误

时间:2017-07-09 16:02:43

标签: python-3.x vector linear-algebra data-science

这是Udacity线性代数复习课程中的一项作业,我已经按照我的方式解决了这个问题,虽然有一个可用于此作业的解决方案我试图以我的方式解决它。但是在找到vectore 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

我们可以看到它们具有相同的角度功能

1 个答案:

答案 0 :(得分:0)

你的第一个程序的问题是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.0000000000000002),因此抛出了数学域错误,并且反余弦值acos(x)仅定义为介于-1和1之间的值。这是由于数值错误在归一化中,可以通过总是略微向上舍入来纠正。