使用python求和两个多项式的问题

问题描述:

我被要求编写一个程序来计算n和m度的两个多项式的相加。我做了两个字典(一个用于第一个多项式,另一个用于另一个多项式),因为每个字典都有作为值和度数的系数作为关键字,所以我可以检查两个字典中的关键字是否相同,然后我可以将他们值。但我不知道为什么我总是得到一个错误。到目前为止我的代码是:使用python求和两个多项式的问题

class poly: 
    def __init__(self, L=[], D=[]): 
     self.coef=L 
     self.deg=D 

    def __add__(self,L2): 
     if len(self.coef)>len(self.deg): 
      dec=dict(zip(self.deg,self.coef)) 
      dec[0]=self.coef[-1] 

     else: 
      dec=dict(zip(self.deg,self.coef)) 

     Dec1=dec 

     if len(L2.coef)>len(L2.deg): 
      dec=dict(zip(L2.deg,L2.coef)) 
      dec[0]=L2.coef[-1] 
     else: 
      dec=dict(zip(L2.deg,L2.coef)) 

     Dec2=dec 
     p=[] 

     if len(Dec2)>len(Dec1): 
      for i in Dec2: 
      if i in Dec1: 
       s=Dec1[i]+Dec2[i] 
       p=p+[s] 
      else: 
       p=p+p[Dec2[i]] 

      for x in Dec1: 
      if x in Dec2: 
       p=p 
      else: 
       p=p+[dec1[x]] 
     return(poly(p)) 

     if len(Dec2)<len(Dec1): 
     for x in Dec1: 
      if x in Dec2: 
       g=Dec1[x] 
       p=p+[g] 
      else: 
       p=p+[Dec1[x]] 

     for m in Dec2: 
      if m in Dec1: 
       p=p 
      else: 
       p=p+[Dec2[m]] 
     return (poly(p)) 

此代码不为我所有的例子,如

>>> p=poly([2,4,7,34],[6,4,2]) 
>>> p1=poly([6,3,7,2,8],[8,4,2,1]) 
>>> p2=p+p1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    p2=p+p1 
    File "poly.py", line 31, in __add__ 
    p=p+p[Dec2[i]] 
IndexError: list index out of range 
>>> #The numbers in the first list is the coefficients and the second list is for degrees 

这不起作用工作!但是,当我在不使用类方法的情况下完成添加时它就起作用了。我是一名初学者,我尽力解决这个问题。

另一个问题是如何写我的代码def str?我真的不知道我应该在一开始写什么。我很抱歉,但我是编程新手,需要一个简单的代码,比如我的代码。

+0

不是说它导致你的特定问题,但要小心使用'[]'作为默认值在'__init__'(或其他地方,就此而言):http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – lvc 2012-04-28 23:04:52

+2

此外,它可能会更有意义将多项式存储为系数的单个列表,以便'x^3 + 2'具有系数'[1,0,2]'。 – lvc 2012-04-28 23:18:25

+0

我都做过了!首先我的init没有[],但它不起作用。所以我会骑它。对不起,没有提到我期待用户输入一个字符串! – user1354396 2012-04-28 23:45:36

  1. 通过共同的约定,类名应该大写(即Poly
  2. 你有__add__做了很多的东西,没有任何与添加。这应该是一个警告标志。
  3. 很多__add__的工作都在关注数据存储格式。也许你应该使用更好的存储格式,不需要太多重新洗牌?
  4. __add__中有很多重复的代码块;这通常是代码应该被分解到子程序中的一个指示器。
  5. 您有此对象(self)更改了另一个对象(L2)的内部细节 - 另一种难闻的气味。

如果移动从__add__自我(if len(self.coef) > len(self.deg) ...)的标准化代码为__init__,这将解决#2,#3,#4的一半,#5于一身去(你不再需要“做到“L2,它会”做“本身)。

如果您意识到这与len(Dec1) > len(Dec2)无关,那么您可以摆脱另一个冗余代码块。这修复了#4的另一半。突然__add__从48行代码缩减到12,并且变得更容易理解和调试。

为了比较的缘故

from itertools import izip_longest, chain, product 
from collections import defaultdict 

class Poly(object): 
    def __init__(self, coeff=None, power=None): 
     if coeff is None: coeff = [] 
     if power is None: power = [] 
     self.d = defaultdict(int) 
     for c,p in izip_longest(coeff, power, fillvalue=0): 
      if c != 0: 
       self.d[p] += c 

    @classmethod 
    def fromDict(cls, d): 
     return cls(d.itervalues(), d.iterkeys()) 

    @property 
    def degree(self): 
     return max(p for p,c in self.d.iteritems() if c != 0) 

    def __add__(self, poly): 
     return Poly(
      chain(self.d.itervalues(), poly.d.itervalues()), 
      chain(self.d.iterkeys(), poly.d.iterkeys()) 
     ) 

    def __mul__(self, poly): 
     return Poly(
      (cs*cp for cs,cp in product(self.d.itervalues(), poly.d.itervalues())), 
      (ps+pp for ps,pp in product(self.d.iterkeys(), poly.d.iterkeys())) 
     ) 

    def __call__(self, x): 
     return sum(c*x**p for p,c in self.d.iteritems()) 

    def __str__(self): 
     clauses = sorted(((p,c) for p,c in self.d.iteritems() if c != 0), reverse=True) 
     return " + ".join("{}x^{}".format(c,p) for p,c in clauses) or "0" 

需要注意的是:

  1. 每种方法很短,不相关的东西就应该完成的唯一的东西。
  2. 我故意写了__init__是非常容错的;它会高兴地接受给定功率的多个系数并对它们进行求和。这使我大大简化了__add____mul__,基本上只是将所有结果子句放在一个新的Poly中,并让它再次清理它们。
  3. 我已经包含了一个最小实现__str__,这将导致像5x^2 + -2x^1 + -5x^0这样的中等难看的输出。您可能希望对负系数和1或0的幂加上特殊处理,以使其产生5x^2 - 2x - 5
  4. 这是为了理解,而不是抄袭;不要将它提交给你的老师,他将永远不会在一百万年内相信你真的写了它;-)